diff options
author | Vasu Dev <vasu.dev@intel.com> | 2009-05-17 08:33:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-18 00:04:08 -0400 |
commit | 184dd3459bb334d9061b58faed3610d08d6c7ff8 (patch) | |
tree | 63c227d4d92dc35269214ecae4654778f966a80d | |
parent | ab6b85c1d7a1bf6c2b27fb542a7b2404e45b7e24 (diff) |
fcoe: adds spma mode support
If we can find a type NETDEV_HW_ADDR_T_SAN mac address from the
corresponding netdev for a fcoe interface then sets up added the
fc->ctlr.spma flag and stores spma mode address in ctl_src_addr.
In case the spma flag is set then:-
1. Adds spma mode MAC address in ctl_src_addr as secondary
MAC address, the FLOGI for FIP and pre-FIP will go out
using this address.
2. Cleans up stored spma MAC address in ctl_src_addr in
fcoe_netdev_cleanup.
3. Sets up spma bit in fip_flags for FIP solicitations along
with exiting FPMA bit setting.
4. Initialize the FLOGI FIP MAC descriptor to stored spma
MAC address in ctl_src_addr. This is used as proposed
FCoE MAC address from initiator along with both SPMA
and FPMA bit set in FIP solicitation, in response the
switch may grant any FPMA or SPMA mode MAC address to
initiator.
Removes FIP descriptor type checking against ELS type
ELS_FLOGI in fcoe_ctlr_encaps to update a FIP MAC descriptor,
instead now checks against FIP_DT_FLOGI.
I've tested this with available FPMA-only FCoE switch but
since data_src_addr is updated using same old code for
both FPMA and SPMA modes with FIP or pre-FIP links, so added
SPMA mode will work with SPMA-only switch also provided that
switch grants a valid MAC address.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 24 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 10 | ||||
-rw-r--r-- | include/scsi/libfcoe.h | 2 |
3 files changed, 33 insertions, 3 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 04f500571d49..f2d16127bd0a 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -238,6 +238,9 @@ void fcoe_netdev_cleanup(struct fcoe_softc *fc) | |||
238 | if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) | 238 | if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) |
239 | dev_unicast_delete(fc->real_dev, | 239 | dev_unicast_delete(fc->real_dev, |
240 | fc->ctlr.data_src_addr, ETH_ALEN); | 240 | fc->ctlr.data_src_addr, ETH_ALEN); |
241 | if (fc->ctlr.spma) | ||
242 | dev_unicast_delete(fc->real_dev, | ||
243 | fc->ctlr.ctl_src_addr, ETH_ALEN); | ||
241 | dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | 244 | dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); |
242 | rtnl_unlock(); | 245 | rtnl_unlock(); |
243 | } | 246 | } |
@@ -257,6 +260,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
257 | u64 wwnn, wwpn; | 260 | u64 wwnn, wwpn; |
258 | struct fcoe_softc *fc; | 261 | struct fcoe_softc *fc; |
259 | u8 flogi_maddr[ETH_ALEN]; | 262 | u8 flogi_maddr[ETH_ALEN]; |
263 | struct netdev_hw_addr *ha; | ||
260 | 264 | ||
261 | /* Setup lport private data to point to fcoe softc */ | 265 | /* Setup lport private data to point to fcoe softc */ |
262 | fc = lport_priv(lp); | 266 | fc = lport_priv(lp); |
@@ -313,9 +317,23 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
313 | skb_queue_head_init(&fc->fcoe_pending_queue); | 317 | skb_queue_head_init(&fc->fcoe_pending_queue); |
314 | fc->fcoe_pending_queue_active = 0; | 318 | fc->fcoe_pending_queue_active = 0; |
315 | 319 | ||
320 | /* look for SAN MAC address, if multiple SAN MACs exist, only | ||
321 | * use the first one for SPMA */ | ||
322 | rcu_read_lock(); | ||
323 | for_each_dev_addr(netdev, ha) { | ||
324 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && | ||
325 | (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) { | ||
326 | memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN); | ||
327 | fc->ctlr.spma = 1; | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | rcu_read_unlock(); | ||
332 | |||
316 | /* setup Source Mac Address */ | 333 | /* setup Source Mac Address */ |
317 | memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, | 334 | if (!fc->ctlr.spma) |
318 | fc->real_dev->addr_len); | 335 | memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, |
336 | fc->real_dev->addr_len); | ||
319 | 337 | ||
320 | wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); | 338 | wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); |
321 | fc_set_wwnn(lp, wwnn); | 339 | fc_set_wwnn(lp, wwnn); |
@@ -331,6 +349,8 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
331 | rtnl_lock(); | 349 | rtnl_lock(); |
332 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | 350 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); |
333 | dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); | 351 | dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); |
352 | if (fc->ctlr.spma) | ||
353 | dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr, ETH_ALEN); | ||
334 | rtnl_unlock(); | 354 | rtnl_unlock(); |
335 | 355 | ||
336 | /* | 356 | /* |
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index f410f4abb548..444a06bdb70b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -198,6 +198,8 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) | |||
198 | sol->fip.fip_subcode = FIP_SC_SOL; | 198 | sol->fip.fip_subcode = FIP_SC_SOL; |
199 | sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW); | 199 | sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW); |
200 | sol->fip.fip_flags = htons(FIP_FL_FPMA); | 200 | sol->fip.fip_flags = htons(FIP_FL_FPMA); |
201 | if (fip->spma) | ||
202 | sol->fip.fip_flags |= htons(FIP_FL_SPMA); | ||
201 | 203 | ||
202 | sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC; | 204 | sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC; |
203 | sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW; | 205 | sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW; |
@@ -350,6 +352,8 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
350 | kal->fip.fip_dl_len = htons((sizeof(kal->mac) + | 352 | kal->fip.fip_dl_len = htons((sizeof(kal->mac) + |
351 | ports * sizeof(*vn)) / FIP_BPW); | 353 | ports * sizeof(*vn)) / FIP_BPW); |
352 | kal->fip.fip_flags = htons(FIP_FL_FPMA); | 354 | kal->fip.fip_flags = htons(FIP_FL_FPMA); |
355 | if (fip->spma) | ||
356 | kal->fip.fip_flags |= htons(FIP_FL_SPMA); | ||
353 | 357 | ||
354 | kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; | 358 | kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; |
355 | kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; | 359 | kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; |
@@ -413,6 +417,8 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
413 | cap->fip.fip_subcode = FIP_SC_REQ; | 417 | cap->fip.fip_subcode = FIP_SC_REQ; |
414 | cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); | 418 | cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); |
415 | cap->fip.fip_flags = htons(FIP_FL_FPMA); | 419 | cap->fip.fip_flags = htons(FIP_FL_FPMA); |
420 | if (fip->spma) | ||
421 | cap->fip.fip_flags |= htons(FIP_FL_SPMA); | ||
416 | 422 | ||
417 | cap->encaps.fd_desc.fip_dtype = dtype; | 423 | cap->encaps.fd_desc.fip_dtype = dtype; |
418 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; | 424 | cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; |
@@ -421,8 +427,10 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
421 | memset(mac, 0, sizeof(mac)); | 427 | memset(mac, 0, sizeof(mac)); |
422 | mac->fd_desc.fip_dtype = FIP_DT_MAC; | 428 | mac->fd_desc.fip_dtype = FIP_DT_MAC; |
423 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; | 429 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; |
424 | if (dtype != ELS_FLOGI) | 430 | if (dtype != FIP_DT_FLOGI) |
425 | memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); | 431 | memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); |
432 | else if (fip->spma) | ||
433 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); | ||
426 | 434 | ||
427 | skb->protocol = htons(ETH_P_802_3); | 435 | skb->protocol = htons(ETH_P_802_3); |
428 | skb_reset_mac_header(skb); | 436 | skb_reset_mac_header(skb); |
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 666cc131732e..b2410605b740 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h | |||
@@ -73,6 +73,7 @@ enum fip_state { | |||
73 | * @link: current link status for libfc. | 73 | * @link: current link status for libfc. |
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 | * @dest_addr: MAC address of the selected FC forwarder. | 77 | * @dest_addr: MAC address of the selected FC forwarder. |
77 | * @ctl_src_addr: the native MAC address of our local port. | 78 | * @ctl_src_addr: the native MAC address of our local port. |
78 | * @data_src_addr: the assigned MAC address for the local port after FLOGI. | 79 | * @data_src_addr: the assigned MAC address for the local port after FLOGI. |
@@ -104,6 +105,7 @@ struct fcoe_ctlr { | |||
104 | u8 link; | 105 | u8 link; |
105 | u8 last_link; | 106 | u8 last_link; |
106 | u8 map_dest; | 107 | u8 map_dest; |
108 | u8 spma; | ||
107 | u8 dest_addr[ETH_ALEN]; | 109 | u8 dest_addr[ETH_ALEN]; |
108 | u8 ctl_src_addr[ETH_ALEN]; | 110 | u8 ctl_src_addr[ETH_ALEN]; |
109 | u8 data_src_addr[ETH_ALEN]; | 111 | u8 data_src_addr[ETH_ALEN]; |