aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2009-05-17 08:33:28 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-18 00:04:08 -0400
commit184dd3459bb334d9061b58faed3610d08d6c7ff8 (patch)
tree63c227d4d92dc35269214ecae4654778f966a80d /drivers/scsi
parentab6b85c1d7a1bf6c2b27fb542a7b2404e45b7e24 (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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/fcoe/fcoe.c24
-rw-r--r--drivers/scsi/fcoe/libfcoe.c10
2 files changed, 31 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);