diff options
-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]; |