diff options
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 147 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.h | 1 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 82 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_elsct.c | 3 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 6 | ||||
-rw-r--r-- | include/scsi/fc_frame.h | 3 | ||||
-rw-r--r-- | include/scsi/libfc.h | 10 | ||||
-rw-r--r-- | include/scsi/libfcoe.h | 15 |
8 files changed, 207 insertions, 60 deletions
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, | |||
226 | } | 226 | } |
227 | 227 | ||
228 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); | 228 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); |
229 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new); | 229 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr); |
230 | static u8 *fcoe_get_src_mac(struct fc_lport *lport); | ||
230 | static void fcoe_destroy_work(struct work_struct *work); | 231 | static void fcoe_destroy_work(struct work_struct *work); |
231 | 232 | ||
232 | /** | 233 | /** |
@@ -254,6 +255,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) | |||
254 | fcoe_ctlr_init(&fcoe->ctlr); | 255 | fcoe_ctlr_init(&fcoe->ctlr); |
255 | fcoe->ctlr.send = fcoe_fip_send; | 256 | fcoe->ctlr.send = fcoe_fip_send; |
256 | fcoe->ctlr.update_mac = fcoe_update_src_mac; | 257 | fcoe->ctlr.update_mac = fcoe_update_src_mac; |
258 | fcoe->ctlr.get_src_addr = fcoe_get_src_mac; | ||
257 | 259 | ||
258 | fcoe_interface_setup(fcoe, netdev); | 260 | fcoe_interface_setup(fcoe, netdev); |
259 | 261 | ||
@@ -286,8 +288,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
286 | /* Delete secondary MAC addresses */ | 288 | /* Delete secondary MAC addresses */ |
287 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | 289 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); |
288 | dev_unicast_delete(netdev, flogi_maddr); | 290 | dev_unicast_delete(netdev, flogi_maddr); |
289 | if (!is_zero_ether_addr(fip->data_src_addr)) | ||
290 | dev_unicast_delete(netdev, fip->data_src_addr); | ||
291 | if (fip->spma) | 291 | if (fip->spma) |
292 | dev_unicast_delete(netdev, fip->ctl_src_addr); | 292 | dev_unicast_delete(netdev, fip->ctl_src_addr); |
293 | dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | 293 | dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); |
@@ -369,26 +369,38 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
369 | 369 | ||
370 | /** | 370 | /** |
371 | * fcoe_update_src_mac() - Update Ethernet MAC filters. | 371 | * fcoe_update_src_mac() - Update Ethernet MAC filters. |
372 | * @fip: FCoE controller. | 372 | * @lport: libfc lport |
373 | * @old: Unicast MAC address to delete if the MAC is non-zero. | 373 | * @addr: Unicast MAC address to add. |
374 | * @new: Unicast MAC address to add. | ||
375 | * | 374 | * |
376 | * Remove any previously-set unicast MAC filter. | 375 | * Remove any previously-set unicast MAC filter. |
377 | * Add secondary FCoE MAC address filter for our OUI. | 376 | * Add secondary FCoE MAC address filter for our OUI. |
378 | */ | 377 | */ |
379 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) | 378 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) |
380 | { | 379 | { |
381 | struct fcoe_interface *fcoe; | 380 | struct fcoe_port *port = lport_priv(lport); |
381 | struct fcoe_interface *fcoe = port->fcoe; | ||
382 | 382 | ||
383 | fcoe = fcoe_from_ctlr(fip); | ||
384 | rtnl_lock(); | 383 | rtnl_lock(); |
385 | if (!is_zero_ether_addr(old)) | 384 | if (!is_zero_ether_addr(port->data_src_addr)) |
386 | dev_unicast_delete(fcoe->netdev, old); | 385 | dev_unicast_delete(fcoe->netdev, port->data_src_addr); |
387 | dev_unicast_add(fcoe->netdev, new); | 386 | if (!is_zero_ether_addr(addr)) |
387 | dev_unicast_add(fcoe->netdev, addr); | ||
388 | memcpy(port->data_src_addr, addr, ETH_ALEN); | ||
388 | rtnl_unlock(); | 389 | rtnl_unlock(); |
389 | } | 390 | } |
390 | 391 | ||
391 | /** | 392 | /** |
393 | * fcoe_get_src_mac() - return the Ethernet source address for an lport | ||
394 | * @lport: libfc lport | ||
395 | */ | ||
396 | static u8 *fcoe_get_src_mac(struct fc_lport *lport) | ||
397 | { | ||
398 | struct fcoe_port *port = lport_priv(lport); | ||
399 | |||
400 | return port->data_src_addr; | ||
401 | } | ||
402 | |||
403 | /** | ||
392 | * fcoe_lport_config() - sets up the fc_lport | 404 | * fcoe_lport_config() - sets up the fc_lport |
393 | * @lp: ptr to the fc_lport | 405 | * @lp: ptr to the fc_lport |
394 | * | 406 | * |
@@ -650,6 +662,11 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
650 | /* Free existing transmit skbs */ | 662 | /* Free existing transmit skbs */ |
651 | fcoe_clean_pending_queue(lport); | 663 | fcoe_clean_pending_queue(lport); |
652 | 664 | ||
665 | rtnl_lock(); | ||
666 | if (!is_zero_ether_addr(port->data_src_addr)) | ||
667 | dev_unicast_delete(netdev, port->data_src_addr); | ||
668 | rtnl_unlock(); | ||
669 | |||
653 | /* receives may not be stopped until after this */ | 670 | /* receives may not be stopped until after this */ |
654 | fcoe_interface_put(fcoe); | 671 | fcoe_interface_put(fcoe); |
655 | 672 | ||
@@ -706,10 +723,16 @@ static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) | |||
706 | return 0; | 723 | return 0; |
707 | } | 724 | } |
708 | 725 | ||
726 | static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, | ||
727 | u32 did, struct fc_frame *fp, unsigned int op, | ||
728 | void (*resp)(struct fc_seq *, struct fc_frame *, void *), | ||
729 | void *arg, u32 timeout); | ||
730 | |||
709 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 731 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
710 | .frame_send = fcoe_xmit, | 732 | .frame_send = fcoe_xmit, |
711 | .ddp_setup = fcoe_ddp_setup, | 733 | .ddp_setup = fcoe_ddp_setup, |
712 | .ddp_done = fcoe_ddp_done, | 734 | .ddp_done = fcoe_ddp_done, |
735 | .elsct_send = fcoe_elsct_send, | ||
713 | }; | 736 | }; |
714 | 737 | ||
715 | /** | 738 | /** |
@@ -1226,7 +1249,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1226 | } | 1249 | } |
1227 | 1250 | ||
1228 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && | 1251 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && |
1229 | fcoe_ctlr_els_send(&fcoe->ctlr, skb)) | 1252 | fcoe_ctlr_els_send(&fcoe->ctlr, lp, skb)) |
1230 | return 0; | 1253 | return 0; |
1231 | 1254 | ||
1232 | sof = fr_sof(fp); | 1255 | sof = fr_sof(fp); |
@@ -1291,7 +1314,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1291 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) | 1314 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) |
1292 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); | 1315 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); |
1293 | else | 1316 | else |
1294 | memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN); | 1317 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); |
1295 | 1318 | ||
1296 | hp = (struct fcoe_hdr *)(eh + 1); | 1319 | hp = (struct fcoe_hdr *)(eh + 1); |
1297 | memset(hp, 0, sizeof(*hp)); | 1320 | memset(hp, 0, sizeof(*hp)); |
@@ -1464,11 +1487,6 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1464 | } | 1487 | } |
1465 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | 1488 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; |
1466 | } | 1489 | } |
1467 | if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) && | ||
1468 | fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) { | ||
1469 | fc_frame_free(fp); | ||
1470 | continue; | ||
1471 | } | ||
1472 | fc_exch_recv(lp, fp); | 1490 | fc_exch_recv(lp, fp); |
1473 | } | 1491 | } |
1474 | return 0; | 1492 | return 0; |
@@ -2061,3 +2079,94 @@ static void __exit fcoe_exit(void) | |||
2061 | fcoe_if_exit(); | 2079 | fcoe_if_exit(); |
2062 | } | 2080 | } |
2063 | module_exit(fcoe_exit); | 2081 | module_exit(fcoe_exit); |
2082 | |||
2083 | /** | ||
2084 | * fcoe_flogi_resp() - FCoE specific FLOGI and FDISC response handler | ||
2085 | * @seq: active sequence in the FLOGI or FDISC exchange | ||
2086 | * @fp: response frame, or error encoded in a pointer (timeout) | ||
2087 | * @arg: pointer the the fcoe_ctlr structure | ||
2088 | * | ||
2089 | * This handles MAC address managment for FCoE, then passes control on to | ||
2090 | * the libfc FLOGI response handler. | ||
2091 | */ | ||
2092 | static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | ||
2093 | { | ||
2094 | struct fcoe_ctlr *fip = arg; | ||
2095 | struct fc_exch *exch = fc_seq_exch(seq); | ||
2096 | struct fc_lport *lport = exch->lp; | ||
2097 | u8 *mac; | ||
2098 | |||
2099 | if (IS_ERR(fp)) | ||
2100 | goto done; | ||
2101 | |||
2102 | mac = fr_cb(fp)->granted_mac; | ||
2103 | if (is_zero_ether_addr(mac)) { | ||
2104 | /* pre-FIP */ | ||
2105 | mac = eth_hdr(&fp->skb)->h_source; | ||
2106 | if (fcoe_ctlr_recv_flogi(fip, lport, fp, mac)) { | ||
2107 | fc_frame_free(fp); | ||
2108 | return; | ||
2109 | } | ||
2110 | } else { | ||
2111 | /* FIP, libfcoe has already seen it */ | ||
2112 | fip->update_mac(lport, fr_cb(fp)->granted_mac); | ||
2113 | } | ||
2114 | done: | ||
2115 | fc_lport_flogi_resp(seq, fp, lport); | ||
2116 | } | ||
2117 | |||
2118 | /** | ||
2119 | * fcoe_logo_resp() - FCoE specific LOGO response handler | ||
2120 | * @seq: active sequence in the LOGO exchange | ||
2121 | * @fp: response frame, or error encoded in a pointer (timeout) | ||
2122 | * @arg: pointer the the fcoe_ctlr structure | ||
2123 | * | ||
2124 | * This handles MAC address managment for FCoE, then passes control on to | ||
2125 | * the libfc LOGO response handler. | ||
2126 | */ | ||
2127 | static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | ||
2128 | { | ||
2129 | struct fcoe_ctlr *fip = arg; | ||
2130 | struct fc_exch *exch = fc_seq_exch(seq); | ||
2131 | struct fc_lport *lport = exch->lp; | ||
2132 | static u8 zero_mac[ETH_ALEN] = { 0 }; | ||
2133 | |||
2134 | if (!IS_ERR(fp)) | ||
2135 | fip->update_mac(lport, zero_mac); | ||
2136 | fc_lport_logo_resp(seq, fp, lport); | ||
2137 | } | ||
2138 | |||
2139 | /** | ||
2140 | * fcoe_elsct_send - FCoE specific ELS handler | ||
2141 | * | ||
2142 | * This does special case handling of FIP encapsualted ELS exchanges for FCoE, | ||
2143 | * using FCoE specific response handlers and passing the FIP controller as | ||
2144 | * the argument (the lport is still available from the exchange). | ||
2145 | * | ||
2146 | * Most of the work here is just handed off to the libfc routine. | ||
2147 | */ | ||
2148 | static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, | ||
2149 | u32 did, struct fc_frame *fp, unsigned int op, | ||
2150 | void (*resp)(struct fc_seq *, struct fc_frame *, void *), | ||
2151 | void *arg, u32 timeout) | ||
2152 | { | ||
2153 | struct fcoe_port *port = lport_priv(lport); | ||
2154 | struct fcoe_interface *fcoe = port->fcoe; | ||
2155 | struct fcoe_ctlr *fip = &fcoe->ctlr; | ||
2156 | struct fc_frame_header *fh = fc_frame_header_get(fp); | ||
2157 | |||
2158 | switch (op) { | ||
2159 | case ELS_FLOGI: | ||
2160 | case ELS_FDISC: | ||
2161 | return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, | ||
2162 | fip, timeout); | ||
2163 | case ELS_LOGO: | ||
2164 | /* only hook onto fabric logouts, not port logouts */ | ||
2165 | if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) | ||
2166 | break; | ||
2167 | return fc_elsct_send(lport, did, fp, op, fcoe_logo_resp, | ||
2168 | fip, timeout); | ||
2169 | } | ||
2170 | return fc_elsct_send(lport, did, fp, op, resp, arg, timeout); | ||
2171 | } | ||
2172 | |||
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 { | |||
104 | u8 fcoe_pending_queue_active; | 104 | u8 fcoe_pending_queue_active; |
105 | struct timer_list timer; /* queue timer */ | 105 | struct timer_list timer; /* queue timer */ |
106 | struct work_struct destroy_work; /* to prevent rtnl deadlocks */ | 106 | struct work_struct destroy_work; /* to prevent rtnl deadlocks */ |
107 | u8 data_src_addr[ETH_ALEN]; | ||
107 | }; | 108 | }; |
108 | 109 | ||
109 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) | 110 | #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); | |||
322 | /** | 322 | /** |
323 | * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF. | 323 | * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF. |
324 | * @fip: FCoE controller. | 324 | * @fip: FCoE controller. |
325 | * @lport: libfc fc_lport to send from | ||
325 | * @ports: 0 for controller keep-alive, 1 for port keep-alive. | 326 | * @ports: 0 for controller keep-alive, 1 for port keep-alive. |
326 | * @sa: source MAC address. | 327 | * @sa: source MAC address. |
327 | * | 328 | * |
@@ -332,7 +333,9 @@ EXPORT_SYMBOL(fcoe_ctlr_link_down); | |||
332 | * The source MAC is the assigned mapped source address. | 333 | * The source MAC is the assigned mapped source address. |
333 | * The destination is the FCF's F-port. | 334 | * The destination is the FCF's F-port. |
334 | */ | 335 | */ |
335 | static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | 336 | static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, |
337 | struct fc_lport *lport, | ||
338 | int ports, u8 *sa) | ||
336 | { | 339 | { |
337 | struct sk_buff *skb; | 340 | struct sk_buff *skb; |
338 | struct fip_kal { | 341 | struct fip_kal { |
@@ -374,16 +377,14 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
374 | kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; | 377 | kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; |
375 | kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; | 378 | kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; |
376 | memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); | 379 | memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); |
377 | |||
378 | if (ports) { | 380 | if (ports) { |
379 | vn = (struct fip_vn_desc *)(kal + 1); | 381 | vn = (struct fip_vn_desc *)(kal + 1); |
380 | vn->fd_desc.fip_dtype = FIP_DT_VN_ID; | 382 | vn->fd_desc.fip_dtype = FIP_DT_VN_ID; |
381 | vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; | 383 | vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; |
382 | memcpy(vn->fd_mac, fip->data_src_addr, ETH_ALEN); | 384 | memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
383 | hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); | 385 | hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); |
384 | put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); | 386 | put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); |
385 | } | 387 | } |
386 | |||
387 | skb_put(skb, len); | 388 | skb_put(skb, len); |
388 | skb->protocol = htons(ETH_P_FIP); | 389 | skb->protocol = htons(ETH_P_FIP); |
389 | skb_reset_mac_header(skb); | 390 | skb_reset_mac_header(skb); |
@@ -394,6 +395,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
394 | /** | 395 | /** |
395 | * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it. | 396 | * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it. |
396 | * @fip: FCoE controller. | 397 | * @fip: FCoE controller. |
398 | * @lport: libfc fc_lport to use for the source address | ||
397 | * @dtype: FIP descriptor type for the frame. | 399 | * @dtype: FIP descriptor type for the frame. |
398 | * @skb: FCoE ELS frame including FC header but no FCoE headers. | 400 | * @skb: FCoE ELS frame including FC header but no FCoE headers. |
399 | * | 401 | * |
@@ -405,7 +407,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
405 | * Headroom includes the FIP encapsulation description, FIP header, and | 407 | * Headroom includes the FIP encapsulation description, FIP header, and |
406 | * Ethernet header. The tailroom is for the FIP MAC descriptor. | 408 | * Ethernet header. The tailroom is for the FIP MAC descriptor. |
407 | */ | 409 | */ |
408 | static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | 410 | static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, |
409 | u8 dtype, struct sk_buff *skb) | 411 | u8 dtype, struct sk_buff *skb) |
410 | { | 412 | { |
411 | struct fip_encaps_head { | 413 | struct fip_encaps_head { |
@@ -450,7 +452,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
450 | mac->fd_desc.fip_dtype = FIP_DT_MAC; | 452 | mac->fd_desc.fip_dtype = FIP_DT_MAC; |
451 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; | 453 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; |
452 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) | 454 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) |
453 | memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); | 455 | memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
454 | else if (fip->spma) | 456 | else if (fip->spma) |
455 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); | 457 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); |
456 | 458 | ||
@@ -463,6 +465,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
463 | /** | 465 | /** |
464 | * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. | 466 | * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. |
465 | * @fip: FCoE controller. | 467 | * @fip: FCoE controller. |
468 | * @lport: libfc fc_lport to send from | ||
466 | * @skb: FCoE ELS frame including FC header but no FCoE headers. | 469 | * @skb: FCoE ELS frame including FC header but no FCoE headers. |
467 | * | 470 | * |
468 | * Returns a non-zero error code if the frame should not be sent. | 471 | * 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, | |||
471 | * The caller must check that the length is a multiple of 4. | 474 | * The caller must check that the length is a multiple of 4. |
472 | * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). | 475 | * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). |
473 | */ | 476 | */ |
474 | int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | 477 | int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, |
478 | struct sk_buff *skb) | ||
475 | { | 479 | { |
476 | struct fc_frame_header *fh; | 480 | struct fc_frame_header *fh; |
477 | u16 old_xid; | 481 | u16 old_xid; |
478 | u8 op; | 482 | u8 op; |
483 | u8 mac[ETH_ALEN]; | ||
479 | 484 | ||
480 | fh = (struct fc_frame_header *)skb->data; | 485 | fh = (struct fc_frame_header *)skb->data; |
481 | op = *(u8 *)(fh + 1); | 486 | op = *(u8 *)(fh + 1); |
@@ -530,14 +535,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
530 | * FLOGI. | 535 | * FLOGI. |
531 | */ | 536 | */ |
532 | fip->flogi_oxid = FC_XID_UNKNOWN; | 537 | fip->flogi_oxid = FC_XID_UNKNOWN; |
533 | fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id); | 538 | fc_fcoe_set_mac(mac, fh->fh_d_id); |
539 | fip->update_mac(lport, mac); | ||
534 | return 0; | 540 | return 0; |
535 | default: | 541 | default: |
536 | if (fip->state != FIP_ST_ENABLED) | 542 | if (fip->state != FIP_ST_ENABLED) |
537 | goto drop; | 543 | goto drop; |
538 | return 0; | 544 | return 0; |
539 | } | 545 | } |
540 | if (fcoe_ctlr_encaps(fip, op, skb)) | 546 | if (fcoe_ctlr_encaps(fip, lport, op, skb)) |
541 | goto drop; | 547 | goto drop; |
542 | fip->send(fip, skb); | 548 | fip->send(fip, skb); |
543 | return -EINPROGRESS; | 549 | return -EINPROGRESS; |
@@ -796,7 +802,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
796 | { | 802 | { |
797 | struct fc_lport *lp = fip->lp; | 803 | struct fc_lport *lp = fip->lp; |
798 | struct fip_header *fiph; | 804 | struct fip_header *fiph; |
799 | struct fc_frame *fp; | 805 | struct fc_frame *fp = (struct fc_frame *)skb; |
800 | struct fc_frame_header *fh = NULL; | 806 | struct fc_frame_header *fh = NULL; |
801 | struct fip_desc *desc; | 807 | struct fip_desc *desc; |
802 | struct fip_encaps *els; | 808 | struct fip_encaps *els; |
@@ -835,6 +841,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
835 | "in FIP ELS\n"); | 841 | "in FIP ELS\n"); |
836 | goto drop; | 842 | goto drop; |
837 | } | 843 | } |
844 | memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); | ||
838 | break; | 845 | break; |
839 | case FIP_DT_FLOGI: | 846 | case FIP_DT_FLOGI: |
840 | case FIP_DT_FDISC: | 847 | case FIP_DT_FDISC: |
@@ -865,13 +872,10 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
865 | goto drop; | 872 | goto drop; |
866 | els_op = *(u8 *)(fh + 1); | 873 | els_op = *(u8 *)(fh + 1); |
867 | 874 | ||
868 | if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) && | 875 | if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP && |
869 | sub == FIP_SC_REP && fip->flogi_oxid == ntohs(fh->fh_ox_id) && | 876 | fip->flogi_oxid == ntohs(fh->fh_ox_id) && |
870 | els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) { | 877 | els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) |
871 | fip->flogi_oxid = FC_XID_UNKNOWN; | 878 | fip->flogi_oxid = FC_XID_UNKNOWN; |
872 | fip->update_mac(fip, fip->data_src_addr, granted_mac); | ||
873 | memcpy(fip->data_src_addr, granted_mac, ETH_ALEN); | ||
874 | } | ||
875 | 879 | ||
876 | /* | 880 | /* |
877 | * Convert skb into an fc_frame containing only the ELS. | 881 | * 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, | |||
958 | if (dlen < sizeof(*vp)) | 962 | if (dlen < sizeof(*vp)) |
959 | return; | 963 | return; |
960 | if (compare_ether_addr(vp->fd_mac, | 964 | if (compare_ether_addr(vp->fd_mac, |
961 | fip->data_src_addr) == 0 && | 965 | fip->get_src_addr(lp)) == 0 && |
962 | get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn && | 966 | get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn && |
963 | ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host)) | 967 | ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host)) |
964 | desc_mask &= ~BIT(FIP_DT_VN_ID); | 968 | desc_mask &= ~BIT(FIP_DT_VN_ID); |
@@ -1113,8 +1117,6 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1113 | struct fcoe_fcf *sel; | 1117 | struct fcoe_fcf *sel; |
1114 | struct fcoe_fcf *fcf; | 1118 | struct fcoe_fcf *fcf; |
1115 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1119 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); |
1116 | u8 send_ctlr_ka; | ||
1117 | u8 send_port_ka; | ||
1118 | 1120 | ||
1119 | spin_lock_bh(&fip->lock); | 1121 | spin_lock_bh(&fip->lock); |
1120 | if (fip->state == FIP_ST_DISABLED) { | 1122 | if (fip->state == FIP_ST_DISABLED) { |
@@ -1153,12 +1155,10 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1153 | schedule_work(&fip->link_work); | 1155 | schedule_work(&fip->link_work); |
1154 | } | 1156 | } |
1155 | 1157 | ||
1156 | send_ctlr_ka = 0; | ||
1157 | send_port_ka = 0; | ||
1158 | if (sel) { | 1158 | if (sel) { |
1159 | if (time_after_eq(jiffies, fip->ctlr_ka_time)) { | 1159 | if (time_after_eq(jiffies, fip->ctlr_ka_time)) { |
1160 | fip->ctlr_ka_time = jiffies + sel->fka_period; | 1160 | fip->ctlr_ka_time = jiffies + sel->fka_period; |
1161 | send_ctlr_ka = 1; | 1161 | fip->send_ctlr_ka = 1; |
1162 | } | 1162 | } |
1163 | if (time_after(next_timer, fip->ctlr_ka_time)) | 1163 | if (time_after(next_timer, fip->ctlr_ka_time)) |
1164 | next_timer = fip->ctlr_ka_time; | 1164 | next_timer = fip->ctlr_ka_time; |
@@ -1166,7 +1166,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1166 | if (time_after_eq(jiffies, fip->port_ka_time)) { | 1166 | if (time_after_eq(jiffies, fip->port_ka_time)) { |
1167 | fip->port_ka_time += jiffies + | 1167 | fip->port_ka_time += jiffies + |
1168 | msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1168 | msecs_to_jiffies(FIP_VN_KA_PERIOD); |
1169 | send_port_ka = 1; | 1169 | fip->send_port_ka = 1; |
1170 | } | 1170 | } |
1171 | if (time_after(next_timer, fip->port_ka_time)) | 1171 | if (time_after(next_timer, fip->port_ka_time)) |
1172 | next_timer = fip->port_ka_time; | 1172 | next_timer = fip->port_ka_time; |
@@ -1176,12 +1176,9 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1176 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); | 1176 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); |
1177 | mod_timer(&fip->timer, next_timer); | 1177 | mod_timer(&fip->timer, next_timer); |
1178 | } | 1178 | } |
1179 | if (fip->send_ctlr_ka || fip->send_port_ka) | ||
1180 | schedule_work(&fip->link_work); | ||
1179 | spin_unlock_bh(&fip->lock); | 1181 | spin_unlock_bh(&fip->lock); |
1180 | |||
1181 | if (send_ctlr_ka) | ||
1182 | fcoe_ctlr_send_keep_alive(fip, 0, fip->ctl_src_addr); | ||
1183 | if (send_port_ka) | ||
1184 | fcoe_ctlr_send_keep_alive(fip, 1, fip->data_src_addr); | ||
1185 | } | 1182 | } |
1186 | 1183 | ||
1187 | /** | 1184 | /** |
@@ -1196,6 +1193,8 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1196 | static void fcoe_ctlr_link_work(struct work_struct *work) | 1193 | static void fcoe_ctlr_link_work(struct work_struct *work) |
1197 | { | 1194 | { |
1198 | struct fcoe_ctlr *fip; | 1195 | struct fcoe_ctlr *fip; |
1196 | struct fc_lport *vport; | ||
1197 | u8 *mac; | ||
1199 | int link; | 1198 | int link; |
1200 | int last_link; | 1199 | int last_link; |
1201 | 1200 | ||
@@ -1212,6 +1211,22 @@ static void fcoe_ctlr_link_work(struct work_struct *work) | |||
1212 | else | 1211 | else |
1213 | fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT); | 1212 | fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT); |
1214 | } | 1213 | } |
1214 | |||
1215 | if (fip->send_ctlr_ka) { | ||
1216 | fip->send_ctlr_ka = 0; | ||
1217 | fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); | ||
1218 | } | ||
1219 | if (fip->send_port_ka) { | ||
1220 | fip->send_port_ka = 0; | ||
1221 | mutex_lock(&fip->lp->lp_mutex); | ||
1222 | mac = fip->get_src_addr(fip->lp); | ||
1223 | fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac); | ||
1224 | list_for_each_entry(vport, &fip->lp->vports, list) { | ||
1225 | mac = fip->get_src_addr(vport); | ||
1226 | fcoe_ctlr_send_keep_alive(fip, vport, 1, mac); | ||
1227 | } | ||
1228 | mutex_unlock(&fip->lp->lp_mutex); | ||
1229 | } | ||
1215 | } | 1230 | } |
1216 | 1231 | ||
1217 | /** | 1232 | /** |
@@ -1236,6 +1251,7 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) | |||
1236 | /** | 1251 | /** |
1237 | * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request. | 1252 | * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request. |
1238 | * @fip: FCoE controller. | 1253 | * @fip: FCoE controller. |
1254 | * @lport: libfc fc_lport instance received on | ||
1239 | * @fp: FC frame. | 1255 | * @fp: FC frame. |
1240 | * @sa: Ethernet source MAC address from received FCoE frame. | 1256 | * @sa: Ethernet source MAC address from received FCoE frame. |
1241 | * | 1257 | * |
@@ -1248,7 +1264,8 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) | |||
1248 | * | 1264 | * |
1249 | * Return non-zero if the frame should not be delivered to libfc. | 1265 | * Return non-zero if the frame should not be delivered to libfc. |
1250 | */ | 1266 | */ |
1251 | int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | 1267 | int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, |
1268 | struct fc_frame *fp, u8 *sa) | ||
1252 | { | 1269 | { |
1253 | struct fc_frame_header *fh; | 1270 | struct fc_frame_header *fh; |
1254 | u8 op; | 1271 | u8 op; |
@@ -1283,11 +1300,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | |||
1283 | fip->map_dest = 0; | 1300 | fip->map_dest = 0; |
1284 | } | 1301 | } |
1285 | fip->flogi_oxid = FC_XID_UNKNOWN; | 1302 | fip->flogi_oxid = FC_XID_UNKNOWN; |
1286 | memcpy(mac, fip->data_src_addr, ETH_ALEN); | 1303 | fc_fcoe_set_mac(mac, fh->fh_d_id); |
1287 | fc_fcoe_set_mac(fip->data_src_addr, fh->fh_d_id); | 1304 | fip->update_mac(lport, mac); |
1288 | spin_unlock_bh(&fip->lock); | 1305 | spin_unlock_bh(&fip->lock); |
1289 | |||
1290 | fip->update_mac(fip, mac, fip->data_src_addr); | ||
1291 | } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { | 1306 | } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { |
1292 | /* | 1307 | /* |
1293 | * Save source MAC for point-to-point responses. | 1308 | * 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) | |||
1370 | return 0; | 1385 | return 0; |
1371 | } | 1386 | } |
1372 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); | 1387 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); |
1388 | |||
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 @@ | |||
31 | /* | 31 | /* |
32 | * fc_elsct_send - sends ELS/CT frame | 32 | * fc_elsct_send - sends ELS/CT frame |
33 | */ | 33 | */ |
34 | static struct fc_seq *fc_elsct_send(struct fc_lport *lport, | 34 | struct fc_seq *fc_elsct_send(struct fc_lport *lport, |
35 | u32 did, | 35 | u32 did, |
36 | struct fc_frame *fp, | 36 | struct fc_frame *fp, |
37 | unsigned int op, | 37 | unsigned int op, |
@@ -63,6 +63,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport, | |||
63 | 63 | ||
64 | return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); | 64 | return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); |
65 | } | 65 | } |
66 | EXPORT_SYMBOL(fc_elsct_send); | ||
66 | 67 | ||
67 | int fc_elsct_init(struct fc_lport *lport) | 68 | int fc_elsct_init(struct fc_lport *lport) |
68 | { | 69 | { |
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) | |||
1320 | * held, but it will lock, call an _enter_* function or fc_lport_error | 1320 | * held, but it will lock, call an _enter_* function or fc_lport_error |
1321 | * and then unlock the lport. | 1321 | * and then unlock the lport. |
1322 | */ | 1322 | */ |
1323 | static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, | 1323 | void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, |
1324 | void *lp_arg) | 1324 | void *lp_arg) |
1325 | { | 1325 | { |
1326 | struct fc_lport *lport = lp_arg; | 1326 | struct fc_lport *lport = lp_arg; |
@@ -1357,6 +1357,7 @@ out: | |||
1357 | err: | 1357 | err: |
1358 | mutex_unlock(&lport->lp_mutex); | 1358 | mutex_unlock(&lport->lp_mutex); |
1359 | } | 1359 | } |
1360 | EXPORT_SYMBOL(fc_lport_logo_resp); | ||
1360 | 1361 | ||
1361 | /** | 1362 | /** |
1362 | * fc_rport_enter_logo() - Logout of the fabric | 1363 | * fc_rport_enter_logo() - Logout of the fabric |
@@ -1397,7 +1398,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) | |||
1397 | * held, but it will lock, call an _enter_* function or fc_lport_error | 1398 | * held, but it will lock, call an _enter_* function or fc_lport_error |
1398 | * and then unlock the lport. | 1399 | * and then unlock the lport. |
1399 | */ | 1400 | */ |
1400 | static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | 1401 | void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, |
1401 | void *lp_arg) | 1402 | void *lp_arg) |
1402 | { | 1403 | { |
1403 | struct fc_lport *lport = lp_arg; | 1404 | struct fc_lport *lport = lp_arg; |
@@ -1480,6 +1481,7 @@ out: | |||
1480 | err: | 1481 | err: |
1481 | mutex_unlock(&lport->lp_mutex); | 1482 | mutex_unlock(&lport->lp_mutex); |
1482 | } | 1483 | } |
1484 | EXPORT_SYMBOL(fc_lport_flogi_resp); | ||
1483 | 1485 | ||
1484 | /** | 1486 | /** |
1485 | * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager | 1487 | * 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 @@ | |||
28 | #include <scsi/fc/fc_fcp.h> | 28 | #include <scsi/fc/fc_fcp.h> |
29 | #include <scsi/fc/fc_encaps.h> | 29 | #include <scsi/fc/fc_encaps.h> |
30 | 30 | ||
31 | #include <linux/if_ether.h> | ||
32 | |||
31 | /* | 33 | /* |
32 | * The fc_frame interface is used to pass frame data between functions. | 34 | * The fc_frame interface is used to pass frame data between functions. |
33 | * The frame includes the data buffer, length, and SOF / EOF delimiter types. | 35 | * The frame includes the data buffer, length, and SOF / EOF delimiter types. |
@@ -67,6 +69,7 @@ struct fcoe_rcv_info { | |||
67 | enum fc_sof fr_sof; /* start of frame delimiter */ | 69 | enum fc_sof fr_sof; /* start of frame delimiter */ |
68 | enum fc_eof fr_eof; /* end of frame delimiter */ | 70 | enum fc_eof fr_eof; /* end of frame delimiter */ |
69 | u8 fr_flags; /* flags - see below */ | 71 | u8 fr_flags; /* flags - see below */ |
72 | u8 granted_mac[ETH_ALEN]; /* FCoE MAC address */ | ||
70 | }; | 73 | }; |
71 | 74 | ||
72 | 75 | ||
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 *); | |||
900 | * Initializes ELS/CT interface | 900 | * Initializes ELS/CT interface |
901 | */ | 901 | */ |
902 | int fc_elsct_init(struct fc_lport *lp); | 902 | int fc_elsct_init(struct fc_lport *lp); |
903 | struct fc_seq *fc_elsct_send(struct fc_lport *lport, | ||
904 | u32 did, | ||
905 | struct fc_frame *fp, | ||
906 | unsigned int op, | ||
907 | void (*resp)(struct fc_seq *, | ||
908 | struct fc_frame *fp, | ||
909 | void *arg), | ||
910 | void *arg, u32 timer_msec); | ||
911 | void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); | ||
912 | void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); | ||
903 | 913 | ||
904 | 914 | ||
905 | /* | 915 | /* |
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 { | |||
74 | * @last_link: last link state reported to libfc. | 74 | * @last_link: last link state reported to libfc. |
75 | * @map_dest: use the FC_MAP mode for destination MAC addresses. | 75 | * @map_dest: use the FC_MAP mode for destination MAC addresses. |
76 | * @spma: supports SPMA server-provided MACs mode | 76 | * @spma: supports SPMA server-provided MACs mode |
77 | * @send_ctlr_ka: need to send controller keep alive | ||
78 | * @send_port_ka: need to send port keep alives | ||
77 | * @dest_addr: MAC address of the selected FC forwarder. | 79 | * @dest_addr: MAC address of the selected FC forwarder. |
78 | * @ctl_src_addr: the native MAC address of our local port. | 80 | * @ctl_src_addr: the native MAC address of our local port. |
79 | * @data_src_addr: the assigned MAC address for the local port after FLOGI. | ||
80 | * @send: LLD-supplied function to handle sending of FIP Ethernet frames. | 81 | * @send: LLD-supplied function to handle sending of FIP Ethernet frames. |
81 | * @update_mac: LLD-supplied function to handle changes to MAC addresses. | 82 | * @update_mac: LLD-supplied function to handle changes to MAC addresses. |
83 | * @get_src_addr: LLD-supplied function to supply a source MAC address. | ||
82 | * @lock: lock protecting this structure. | 84 | * @lock: lock protecting this structure. |
83 | * | 85 | * |
84 | * This structure is used by all FCoE drivers. It contains information | 86 | * This structure is used by all FCoE drivers. It contains information |
@@ -106,12 +108,14 @@ struct fcoe_ctlr { | |||
106 | u8 last_link; | 108 | u8 last_link; |
107 | u8 map_dest; | 109 | u8 map_dest; |
108 | u8 spma; | 110 | u8 spma; |
111 | u8 send_ctlr_ka; | ||
112 | u8 send_port_ka; | ||
109 | u8 dest_addr[ETH_ALEN]; | 113 | u8 dest_addr[ETH_ALEN]; |
110 | u8 ctl_src_addr[ETH_ALEN]; | 114 | u8 ctl_src_addr[ETH_ALEN]; |
111 | u8 data_src_addr[ETH_ALEN]; | ||
112 | 115 | ||
113 | void (*send)(struct fcoe_ctlr *, struct sk_buff *); | 116 | void (*send)(struct fcoe_ctlr *, struct sk_buff *); |
114 | void (*update_mac)(struct fcoe_ctlr *, u8 *old, u8 *new); | 117 | void (*update_mac)(struct fc_lport *, u8 *addr); |
118 | u8 * (*get_src_addr)(struct fc_lport *); | ||
115 | spinlock_t lock; | 119 | spinlock_t lock; |
116 | }; | 120 | }; |
117 | 121 | ||
@@ -155,9 +159,10 @@ void fcoe_ctlr_init(struct fcoe_ctlr *); | |||
155 | void fcoe_ctlr_destroy(struct fcoe_ctlr *); | 159 | void fcoe_ctlr_destroy(struct fcoe_ctlr *); |
156 | void fcoe_ctlr_link_up(struct fcoe_ctlr *); | 160 | void fcoe_ctlr_link_up(struct fcoe_ctlr *); |
157 | int fcoe_ctlr_link_down(struct fcoe_ctlr *); | 161 | int fcoe_ctlr_link_down(struct fcoe_ctlr *); |
158 | int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct sk_buff *); | 162 | int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct fc_lport *, struct sk_buff *); |
159 | void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *); | 163 | void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *); |
160 | int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_frame *fp, u8 *sa); | 164 | int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *lport, |
165 | struct fc_frame *fp, u8 *sa); | ||
161 | 166 | ||
162 | /* libfcoe funcs */ | 167 | /* libfcoe funcs */ |
163 | u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); | 168 | u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); |