diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-16 20:24:53 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-16 20:24:53 -0400 |
commit | 492b057c426e4aa747484958e18e9da29003985d (patch) | |
tree | 34e08c24618688d8bcc190523028b5f94cce0c0b /drivers/scsi/fcoe/fcoe.c | |
parent | 313485175da221c388f6a8ecf4c30062ba9bea17 (diff) | |
parent | 300df7dc89cc276377fc020704e34875d5c473b6 (diff) |
Merge commit 'origin/master' into next
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 197 |
1 files changed, 115 insertions, 82 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index e606b4829d44..c15878e88157 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -135,6 +135,58 @@ static struct scsi_host_template fcoe_shost_template = { | |||
135 | }; | 135 | }; |
136 | 136 | ||
137 | /** | 137 | /** |
138 | * fcoe_fip_recv - handle a received FIP frame. | ||
139 | * @skb: the receive skb | ||
140 | * @dev: associated &net_device | ||
141 | * @ptype: the &packet_type structure which was used to register this handler. | ||
142 | * @orig_dev: original receive &net_device, in case @dev is a bond. | ||
143 | * | ||
144 | * Returns: 0 for success | ||
145 | */ | ||
146 | static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | ||
147 | struct packet_type *ptype, | ||
148 | struct net_device *orig_dev) | ||
149 | { | ||
150 | struct fcoe_softc *fc; | ||
151 | |||
152 | fc = container_of(ptype, struct fcoe_softc, fip_packet_type); | ||
153 | fcoe_ctlr_recv(&fc->ctlr, skb); | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. | ||
159 | * @fip: FCoE controller. | ||
160 | * @skb: FIP Packet. | ||
161 | */ | ||
162 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | ||
163 | { | ||
164 | skb->dev = fcoe_from_ctlr(fip)->real_dev; | ||
165 | dev_queue_xmit(skb); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * fcoe_update_src_mac() - Update Ethernet MAC filters. | ||
170 | * @fip: FCoE controller. | ||
171 | * @old: Unicast MAC address to delete if the MAC is non-zero. | ||
172 | * @new: Unicast MAC address to add. | ||
173 | * | ||
174 | * Remove any previously-set unicast MAC filter. | ||
175 | * Add secondary FCoE MAC address filter for our OUI. | ||
176 | */ | ||
177 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) | ||
178 | { | ||
179 | struct fcoe_softc *fc; | ||
180 | |||
181 | fc = fcoe_from_ctlr(fip); | ||
182 | rtnl_lock(); | ||
183 | if (!is_zero_ether_addr(old)) | ||
184 | dev_unicast_delete(fc->real_dev, old); | ||
185 | dev_unicast_add(fc->real_dev, new); | ||
186 | rtnl_unlock(); | ||
187 | } | ||
188 | |||
189 | /** | ||
138 | * fcoe_lport_config() - sets up the fc_lport | 190 | * fcoe_lport_config() - sets up the fc_lport |
139 | * @lp: ptr to the fc_lport | 191 | * @lp: ptr to the fc_lport |
140 | * | 192 | * |
@@ -167,6 +219,30 @@ static int fcoe_lport_config(struct fc_lport *lp) | |||
167 | } | 219 | } |
168 | 220 | ||
169 | /** | 221 | /** |
222 | * fcoe_netdev_cleanup() - clean up netdev configurations | ||
223 | * @fc: ptr to the fcoe_softc | ||
224 | */ | ||
225 | void fcoe_netdev_cleanup(struct fcoe_softc *fc) | ||
226 | { | ||
227 | u8 flogi_maddr[ETH_ALEN]; | ||
228 | |||
229 | /* Don't listen for Ethernet packets anymore */ | ||
230 | dev_remove_pack(&fc->fcoe_packet_type); | ||
231 | dev_remove_pack(&fc->fip_packet_type); | ||
232 | |||
233 | /* Delete secondary MAC addresses */ | ||
234 | rtnl_lock(); | ||
235 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | ||
236 | dev_unicast_delete(fc->real_dev, flogi_maddr); | ||
237 | if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) | ||
238 | dev_unicast_delete(fc->real_dev, fc->ctlr.data_src_addr); | ||
239 | if (fc->ctlr.spma) | ||
240 | dev_unicast_delete(fc->real_dev, fc->ctlr.ctl_src_addr); | ||
241 | dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | ||
242 | rtnl_unlock(); | ||
243 | } | ||
244 | |||
245 | /** | ||
170 | * fcoe_queue_timer() - fcoe queue timer | 246 | * fcoe_queue_timer() - fcoe queue timer |
171 | * @lp: the fc_lport pointer | 247 | * @lp: the fc_lport pointer |
172 | * | 248 | * |
@@ -193,6 +269,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
193 | u64 wwnn, wwpn; | 269 | u64 wwnn, wwpn; |
194 | struct fcoe_softc *fc; | 270 | struct fcoe_softc *fc; |
195 | u8 flogi_maddr[ETH_ALEN]; | 271 | u8 flogi_maddr[ETH_ALEN]; |
272 | struct netdev_hw_addr *ha; | ||
196 | 273 | ||
197 | /* Setup lport private data to point to fcoe softc */ | 274 | /* Setup lport private data to point to fcoe softc */ |
198 | fc = lport_priv(lp); | 275 | fc = lport_priv(lp); |
@@ -250,9 +327,23 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
250 | fc->fcoe_pending_queue_active = 0; | 327 | fc->fcoe_pending_queue_active = 0; |
251 | setup_timer(&fc->timer, fcoe_queue_timer, (unsigned long)lp); | 328 | setup_timer(&fc->timer, fcoe_queue_timer, (unsigned long)lp); |
252 | 329 | ||
330 | /* look for SAN MAC address, if multiple SAN MACs exist, only | ||
331 | * use the first one for SPMA */ | ||
332 | rcu_read_lock(); | ||
333 | for_each_dev_addr(netdev, ha) { | ||
334 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && | ||
335 | (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) { | ||
336 | memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN); | ||
337 | fc->ctlr.spma = 1; | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | rcu_read_unlock(); | ||
342 | |||
253 | /* setup Source Mac Address */ | 343 | /* setup Source Mac Address */ |
254 | memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, | 344 | if (!fc->ctlr.spma) |
255 | fc->real_dev->addr_len); | 345 | memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr, |
346 | fc->real_dev->addr_len); | ||
256 | 347 | ||
257 | wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); | 348 | wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0); |
258 | fc_set_wwnn(lp, wwnn); | 349 | fc_set_wwnn(lp, wwnn); |
@@ -267,7 +358,9 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
267 | */ | 358 | */ |
268 | rtnl_lock(); | 359 | rtnl_lock(); |
269 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | 360 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); |
270 | dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); | 361 | dev_unicast_add(fc->real_dev, flogi_maddr); |
362 | if (fc->ctlr.spma) | ||
363 | dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr); | ||
271 | dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | 364 | dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); |
272 | rtnl_unlock(); | 365 | rtnl_unlock(); |
273 | 366 | ||
@@ -280,6 +373,11 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
280 | fc->fcoe_packet_type.dev = fc->real_dev; | 373 | fc->fcoe_packet_type.dev = fc->real_dev; |
281 | dev_add_pack(&fc->fcoe_packet_type); | 374 | dev_add_pack(&fc->fcoe_packet_type); |
282 | 375 | ||
376 | fc->fip_packet_type.func = fcoe_fip_recv; | ||
377 | fc->fip_packet_type.type = htons(ETH_P_FIP); | ||
378 | fc->fip_packet_type.dev = fc->real_dev; | ||
379 | dev_add_pack(&fc->fip_packet_type); | ||
380 | |||
283 | return 0; | 381 | return 0; |
284 | } | 382 | } |
285 | 383 | ||
@@ -347,7 +445,6 @@ static int fcoe_if_destroy(struct net_device *netdev) | |||
347 | { | 445 | { |
348 | struct fc_lport *lp = NULL; | 446 | struct fc_lport *lp = NULL; |
349 | struct fcoe_softc *fc; | 447 | struct fcoe_softc *fc; |
350 | u8 flogi_maddr[ETH_ALEN]; | ||
351 | 448 | ||
352 | BUG_ON(!netdev); | 449 | BUG_ON(!netdev); |
353 | 450 | ||
@@ -366,9 +463,10 @@ static int fcoe_if_destroy(struct net_device *netdev) | |||
366 | /* Remove the instance from fcoe's list */ | 463 | /* Remove the instance from fcoe's list */ |
367 | fcoe_hostlist_remove(lp); | 464 | fcoe_hostlist_remove(lp); |
368 | 465 | ||
369 | /* Don't listen for Ethernet packets anymore */ | 466 | /* clean up netdev configurations */ |
370 | dev_remove_pack(&fc->fcoe_packet_type); | 467 | fcoe_netdev_cleanup(fc); |
371 | dev_remove_pack(&fc->fip_packet_type); | 468 | |
469 | /* tear-down the FCoE controller */ | ||
372 | fcoe_ctlr_destroy(&fc->ctlr); | 470 | fcoe_ctlr_destroy(&fc->ctlr); |
373 | 471 | ||
374 | /* Cleanup the fc_lport */ | 472 | /* Cleanup the fc_lport */ |
@@ -383,16 +481,6 @@ static int fcoe_if_destroy(struct net_device *netdev) | |||
383 | if (lp->emp) | 481 | if (lp->emp) |
384 | fc_exch_mgr_free(lp->emp); | 482 | fc_exch_mgr_free(lp->emp); |
385 | 483 | ||
386 | /* Delete secondary MAC addresses */ | ||
387 | rtnl_lock(); | ||
388 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | ||
389 | dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN); | ||
390 | if (!is_zero_ether_addr(fc->ctlr.data_src_addr)) | ||
391 | dev_unicast_delete(fc->real_dev, | ||
392 | fc->ctlr.data_src_addr, ETH_ALEN); | ||
393 | dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | ||
394 | rtnl_unlock(); | ||
395 | |||
396 | /* Free the per-CPU receive threads */ | 484 | /* Free the per-CPU receive threads */ |
397 | fcoe_percpu_clean(lp); | 485 | fcoe_percpu_clean(lp); |
398 | 486 | ||
@@ -455,58 +543,6 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { | |||
455 | }; | 543 | }; |
456 | 544 | ||
457 | /** | 545 | /** |
458 | * fcoe_fip_recv - handle a received FIP frame. | ||
459 | * @skb: the receive skb | ||
460 | * @dev: associated &net_device | ||
461 | * @ptype: the &packet_type structure which was used to register this handler. | ||
462 | * @orig_dev: original receive &net_device, in case @dev is a bond. | ||
463 | * | ||
464 | * Returns: 0 for success | ||
465 | */ | ||
466 | static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | ||
467 | struct packet_type *ptype, | ||
468 | struct net_device *orig_dev) | ||
469 | { | ||
470 | struct fcoe_softc *fc; | ||
471 | |||
472 | fc = container_of(ptype, struct fcoe_softc, fip_packet_type); | ||
473 | fcoe_ctlr_recv(&fc->ctlr, skb); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. | ||
479 | * @fip: FCoE controller. | ||
480 | * @skb: FIP Packet. | ||
481 | */ | ||
482 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | ||
483 | { | ||
484 | skb->dev = fcoe_from_ctlr(fip)->real_dev; | ||
485 | dev_queue_xmit(skb); | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * fcoe_update_src_mac() - Update Ethernet MAC filters. | ||
490 | * @fip: FCoE controller. | ||
491 | * @old: Unicast MAC address to delete if the MAC is non-zero. | ||
492 | * @new: Unicast MAC address to add. | ||
493 | * | ||
494 | * Remove any previously-set unicast MAC filter. | ||
495 | * Add secondary FCoE MAC address filter for our OUI. | ||
496 | */ | ||
497 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) | ||
498 | { | ||
499 | struct fcoe_softc *fc; | ||
500 | |||
501 | fc = fcoe_from_ctlr(fip); | ||
502 | rtnl_lock(); | ||
503 | if (!is_zero_ether_addr(old)) | ||
504 | dev_unicast_delete(fc->real_dev, old, ETH_ALEN); | ||
505 | dev_unicast_add(fc->real_dev, new, ETH_ALEN); | ||
506 | rtnl_unlock(); | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * fcoe_if_create() - this function creates the fcoe interface | 546 | * fcoe_if_create() - this function creates the fcoe interface |
511 | * @netdev: pointer the associated netdevice | 547 | * @netdev: pointer the associated netdevice |
512 | * | 548 | * |
@@ -547,13 +583,6 @@ static int fcoe_if_create(struct net_device *netdev) | |||
547 | goto out_host_put; | 583 | goto out_host_put; |
548 | } | 584 | } |
549 | 585 | ||
550 | /* configure lport network properties */ | ||
551 | rc = fcoe_netdev_config(lp, netdev); | ||
552 | if (rc) { | ||
553 | FC_DBG("Could not configure netdev for lport\n"); | ||
554 | goto out_host_put; | ||
555 | } | ||
556 | |||
557 | /* | 586 | /* |
558 | * Initialize FIP. | 587 | * Initialize FIP. |
559 | */ | 588 | */ |
@@ -561,23 +590,25 @@ static int fcoe_if_create(struct net_device *netdev) | |||
561 | fc->ctlr.send = fcoe_fip_send; | 590 | fc->ctlr.send = fcoe_fip_send; |
562 | fc->ctlr.update_mac = fcoe_update_src_mac; | 591 | fc->ctlr.update_mac = fcoe_update_src_mac; |
563 | 592 | ||
564 | fc->fip_packet_type.func = fcoe_fip_recv; | 593 | /* configure lport network properties */ |
565 | fc->fip_packet_type.type = htons(ETH_P_FIP); | 594 | rc = fcoe_netdev_config(lp, netdev); |
566 | fc->fip_packet_type.dev = fc->real_dev; | 595 | if (rc) { |
567 | dev_add_pack(&fc->fip_packet_type); | 596 | FC_DBG("Could not configure netdev for the interface\n"); |
597 | goto out_netdev_cleanup; | ||
598 | } | ||
568 | 599 | ||
569 | /* configure lport scsi host properties */ | 600 | /* configure lport scsi host properties */ |
570 | rc = fcoe_shost_config(lp, shost, &netdev->dev); | 601 | rc = fcoe_shost_config(lp, shost, &netdev->dev); |
571 | if (rc) { | 602 | if (rc) { |
572 | FC_DBG("Could not configure shost for lport\n"); | 603 | FC_DBG("Could not configure shost for lport\n"); |
573 | goto out_host_put; | 604 | goto out_netdev_cleanup; |
574 | } | 605 | } |
575 | 606 | ||
576 | /* lport exch manager allocation */ | 607 | /* lport exch manager allocation */ |
577 | rc = fcoe_em_config(lp); | 608 | rc = fcoe_em_config(lp); |
578 | if (rc) { | 609 | if (rc) { |
579 | FC_DBG("Could not configure em for lport\n"); | 610 | FC_DBG("Could not configure em for lport\n"); |
580 | goto out_host_put; | 611 | goto out_netdev_cleanup; |
581 | } | 612 | } |
582 | 613 | ||
583 | /* Initialize the library */ | 614 | /* Initialize the library */ |
@@ -603,6 +634,8 @@ static int fcoe_if_create(struct net_device *netdev) | |||
603 | 634 | ||
604 | out_lp_destroy: | 635 | out_lp_destroy: |
605 | fc_exch_mgr_free(lp->emp); /* Free the EM */ | 636 | fc_exch_mgr_free(lp->emp); /* Free the EM */ |
637 | out_netdev_cleanup: | ||
638 | fcoe_netdev_cleanup(fc); | ||
606 | out_host_put: | 639 | out_host_put: |
607 | scsi_host_put(lp->host); | 640 | scsi_host_put(lp->host); |
608 | return rc; | 641 | return rc; |