summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c303
1 files changed, 167 insertions, 136 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index e606b4829d44..0a5609bb5817 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -45,8 +45,6 @@
#include "fcoe.h"
-static int debug_fcoe;
-
MODULE_AUTHOR("Open-FCoE.org");
MODULE_DESCRIPTION("FCoE");
MODULE_LICENSE("GPL v2");
@@ -135,6 +133,58 @@ static struct scsi_host_template fcoe_shost_template = {
};
/**
+ * fcoe_fip_recv - handle a received FIP frame.
+ * @skb: the receive skb
+ * @dev: associated &net_device
+ * @ptype: the &packet_type structure which was used to register this handler.
+ * @orig_dev: original receive &net_device, in case @dev is a bond.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype,
+ struct net_device *orig_dev)
+{
+ struct fcoe_softc *fc;
+
+ fc = container_of(ptype, struct fcoe_softc, fip_packet_type);
+ fcoe_ctlr_recv(&fc->ctlr, skb);
+ return 0;
+}
+
+/**
+ * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame.
+ * @fip: FCoE controller.
+ * @skb: FIP Packet.
+ */
+static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+ skb->dev = fcoe_from_ctlr(fip)->real_dev;
+ dev_queue_xmit(skb);
+}
+
+/**
+ * fcoe_update_src_mac() - Update Ethernet MAC filters.
+ * @fip: FCoE controller.
+ * @old: Unicast MAC address to delete if the MAC is non-zero.
+ * @new: Unicast MAC address to add.
+ *
+ * Remove any previously-set unicast MAC filter.
+ * Add secondary FCoE MAC address filter for our OUI.
+ */
+static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
+{
+ struct fcoe_softc *fc;
+
+ fc = fcoe_from_ctlr(fip);
+ rtnl_lock();
+ if (!is_zero_ether_addr(old))
+ dev_unicast_delete(fc->real_dev, old);
+ dev_unicast_add(fc->real_dev, new);
+ rtnl_unlock();
+}
+
+/**
* fcoe_lport_config() - sets up the fc_lport
* @lp: ptr to the fc_lport
*
@@ -167,6 +217,30 @@ static int fcoe_lport_config(struct fc_lport *lp)
}
/**
+ * fcoe_netdev_cleanup() - clean up netdev configurations
+ * @fc: ptr to the fcoe_softc
+ */
+void fcoe_netdev_cleanup(struct fcoe_softc *fc)
+{
+ u8 flogi_maddr[ETH_ALEN];
+
+ /* Don't listen for Ethernet packets anymore */
+ dev_remove_pack(&fc->fcoe_packet_type);
+ dev_remove_pack(&fc->fip_packet_type);
+
+ /* Delete secondary MAC addresses */
+ rtnl_lock();
+ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
+ dev_unicast_delete(fc->real_dev, flogi_maddr);
+ if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
+ dev_unicast_delete(fc->real_dev, fc->ctlr.data_src_addr);
+ if (fc->ctlr.spma)
+ dev_unicast_delete(fc->real_dev, fc->ctlr.ctl_src_addr);
+ dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+ rtnl_unlock();
+}
+
+/**
* fcoe_queue_timer() - fcoe queue timer
* @lp: the fc_lport pointer
*
@@ -193,6 +267,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
u64 wwnn, wwpn;
struct fcoe_softc *fc;
u8 flogi_maddr[ETH_ALEN];
+ struct netdev_hw_addr *ha;
/* Setup lport private data to point to fcoe softc */
fc = lport_priv(lp);
@@ -228,31 +303,44 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
#ifdef NETIF_F_FCOE_CRC
if (netdev->features & NETIF_F_FCOE_CRC) {
lp->crc_offload = 1;
- printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
- netdev->name);
+ FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
}
#endif
#ifdef NETIF_F_FSO
if (netdev->features & NETIF_F_FSO) {
lp->seq_offload = 1;
lp->lso_max = netdev->gso_max_size;
- printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
- netdev->name, lp->lso_max);
+ FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
+ lp->lso_max);
}
#endif
if (netdev->fcoe_ddp_xid) {
lp->lro_enabled = 1;
lp->lro_xid = netdev->fcoe_ddp_xid;
- printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
- netdev->name, lp->lro_xid);
+ FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
+ lp->lro_xid);
}
skb_queue_head_init(&fc->fcoe_pending_queue);
fc->fcoe_pending_queue_active = 0;
setup_timer(&fc->timer, fcoe_queue_timer, (unsigned long)lp);
+ /* look for SAN MAC address, if multiple SAN MACs exist, only
+ * use the first one for SPMA */
+ rcu_read_lock();
+ for_each_dev_addr(netdev, ha) {
+ if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
+ (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) {
+ memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+ fc->ctlr.spma = 1;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
/* setup Source Mac Address */
- memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr,
- fc->real_dev->addr_len);
+ if (!fc->ctlr.spma)
+ memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr,
+ fc->real_dev->addr_len);
wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
fc_set_wwnn(lp, wwnn);
@@ -267,7 +355,9 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
*/
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
- dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
+ dev_unicast_add(fc->real_dev, flogi_maddr);
+ if (fc->ctlr.spma)
+ dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr);
dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
@@ -280,6 +370,11 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
fc->fcoe_packet_type.dev = fc->real_dev;
dev_add_pack(&fc->fcoe_packet_type);
+ fc->fip_packet_type.func = fcoe_fip_recv;
+ fc->fip_packet_type.type = htons(ETH_P_FIP);
+ fc->fip_packet_type.dev = fc->real_dev;
+ dev_add_pack(&fc->fip_packet_type);
+
return 0;
}
@@ -309,7 +404,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
/* add the new host to the SCSI-ml */
rc = scsi_add_host(lp->host, dev);
if (rc) {
- FC_DBG("fcoe_shost_config:error on scsi_add_host\n");
+ FCOE_NETDEV_DBG(fcoe_netdev(lp), "fcoe_shost_config: "
+ "error on scsi_add_host\n");
return rc;
}
sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
@@ -347,12 +443,10 @@ static int fcoe_if_destroy(struct net_device *netdev)
{
struct fc_lport *lp = NULL;
struct fcoe_softc *fc;
- u8 flogi_maddr[ETH_ALEN];
BUG_ON(!netdev);
- printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n",
- netdev->name);
+ FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
lp = fcoe_hostlist_lookup(netdev);
if (!lp)
@@ -366,9 +460,10 @@ static int fcoe_if_destroy(struct net_device *netdev)
/* Remove the instance from fcoe's list */
fcoe_hostlist_remove(lp);
- /* Don't listen for Ethernet packets anymore */
- dev_remove_pack(&fc->fcoe_packet_type);
- dev_remove_pack(&fc->fip_packet_type);
+ /* clean up netdev configurations */
+ fcoe_netdev_cleanup(fc);
+
+ /* tear-down the FCoE controller */
fcoe_ctlr_destroy(&fc->ctlr);
/* Cleanup the fc_lport */
@@ -383,16 +478,6 @@ static int fcoe_if_destroy(struct net_device *netdev)
if (lp->emp)
fc_exch_mgr_free(lp->emp);
- /* Delete secondary MAC addresses */
- rtnl_lock();
- memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
- dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
- if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
- dev_unicast_delete(fc->real_dev,
- fc->ctlr.data_src_addr, ETH_ALEN);
- dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
- rtnl_unlock();
-
/* Free the per-CPU receive threads */
fcoe_percpu_clean(lp);
@@ -455,58 +540,6 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
};
/**
- * fcoe_fip_recv - handle a received FIP frame.
- * @skb: the receive skb
- * @dev: associated &net_device
- * @ptype: the &packet_type structure which was used to register this handler.
- * @orig_dev: original receive &net_device, in case @dev is a bond.
- *
- * Returns: 0 for success
- */
-static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype,
- struct net_device *orig_dev)
-{
- struct fcoe_softc *fc;
-
- fc = container_of(ptype, struct fcoe_softc, fip_packet_type);
- fcoe_ctlr_recv(&fc->ctlr, skb);
- return 0;
-}
-
-/**
- * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame.
- * @fip: FCoE controller.
- * @skb: FIP Packet.
- */
-static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
- skb->dev = fcoe_from_ctlr(fip)->real_dev;
- dev_queue_xmit(skb);
-}
-
-/**
- * fcoe_update_src_mac() - Update Ethernet MAC filters.
- * @fip: FCoE controller.
- * @old: Unicast MAC address to delete if the MAC is non-zero.
- * @new: Unicast MAC address to add.
- *
- * Remove any previously-set unicast MAC filter.
- * Add secondary FCoE MAC address filter for our OUI.
- */
-static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
-{
- struct fcoe_softc *fc;
-
- fc = fcoe_from_ctlr(fip);
- rtnl_lock();
- if (!is_zero_ether_addr(old))
- dev_unicast_delete(fc->real_dev, old, ETH_ALEN);
- dev_unicast_add(fc->real_dev, new, ETH_ALEN);
- rtnl_unlock();
-}
-
-/**
* fcoe_if_create() - this function creates the fcoe interface
* @netdev: pointer the associated netdevice
*
@@ -524,8 +557,7 @@ static int fcoe_if_create(struct net_device *netdev)
BUG_ON(!netdev);
- printk(KERN_DEBUG "fcoe_if_create:interface on %s\n",
- netdev->name);
+ FCOE_NETDEV_DBG(netdev, "Create Interface\n");
lp = fcoe_hostlist_lookup(netdev);
if (lp)
@@ -534,7 +566,7 @@ static int fcoe_if_create(struct net_device *netdev)
shost = libfc_host_alloc(&fcoe_shost_template,
sizeof(struct fcoe_softc));
if (!shost) {
- FC_DBG("Could not allocate host structure\n");
+ FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
return -ENOMEM;
}
lp = shost_priv(shost);
@@ -543,14 +575,8 @@ static int fcoe_if_create(struct net_device *netdev)
/* configure fc_lport, e.g., em */
rc = fcoe_lport_config(lp);
if (rc) {
- FC_DBG("Could not configure lport\n");
- goto out_host_put;
- }
-
- /* configure lport network properties */
- rc = fcoe_netdev_config(lp, netdev);
- if (rc) {
- FC_DBG("Could not configure netdev for lport\n");
+ FCOE_NETDEV_DBG(netdev, "Could not configure lport for the "
+ "interface\n");
goto out_host_put;
}
@@ -561,29 +587,35 @@ static int fcoe_if_create(struct net_device *netdev)
fc->ctlr.send = fcoe_fip_send;
fc->ctlr.update_mac = fcoe_update_src_mac;
- fc->fip_packet_type.func = fcoe_fip_recv;
- fc->fip_packet_type.type = htons(ETH_P_FIP);
- fc->fip_packet_type.dev = fc->real_dev;
- dev_add_pack(&fc->fip_packet_type);
+ /* configure lport network properties */
+ rc = fcoe_netdev_config(lp, netdev);
+ if (rc) {
+ FCOE_NETDEV_DBG(netdev, "Could not configure netdev for the "
+ "interface\n");
+ goto out_netdev_cleanup;
+ }
/* configure lport scsi host properties */
rc = fcoe_shost_config(lp, shost, &netdev->dev);
if (rc) {
- FC_DBG("Could not configure shost for lport\n");
- goto out_host_put;
+ FCOE_NETDEV_DBG(netdev, "Could not configure shost for the "
+ "interface\n");
+ goto out_netdev_cleanup;
}
/* lport exch manager allocation */
rc = fcoe_em_config(lp);
if (rc) {
- FC_DBG("Could not configure em for lport\n");
- goto out_host_put;
+ FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
+ "interface\n");
+ goto out_netdev_cleanup;
}
/* Initialize the library */
rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
if (rc) {
- FC_DBG("Could not configure libfc for lport!\n");
+ FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
+ "interface\n");
goto out_lp_destroy;
}
@@ -603,6 +635,8 @@ static int fcoe_if_create(struct net_device *netdev)
out_lp_destroy:
fc_exch_mgr_free(lp->emp); /* Free the EM */
+out_netdev_cleanup:
+ fcoe_netdev_cleanup(fc);
out_host_put:
scsi_host_put(lp->host);
return rc;
@@ -620,7 +654,7 @@ static int __init fcoe_if_init(void)
fc_attach_transport(&fcoe_transport_function);
if (!scsi_transport_fcoe_sw) {
- printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n");
+ printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n");
return -ENODEV;
}
@@ -681,7 +715,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
unsigned targ_cpu = smp_processor_id();
#endif /* CONFIG_SMP */
- printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu);
+ FCOE_DBG("Destroying receive thread for CPU %d\n", cpu);
/* Prevent any new skbs from being queued for this CPU. */
p = &per_cpu(fcoe_percpu, cpu);
@@ -703,8 +737,8 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
p0 = &per_cpu(fcoe_percpu, targ_cpu);
spin_lock_bh(&p0->fcoe_rx_list.lock);
if (p0->thread) {
- FC_DBG("Moving frames from CPU %d to CPU %d\n",
- cpu, targ_cpu);
+ FCOE_DBG("Moving frames from CPU %d to CPU %d\n",
+ cpu, targ_cpu);
while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
__skb_queue_tail(&p0->fcoe_rx_list, skb);
@@ -770,12 +804,12 @@ static int fcoe_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
- FC_DBG("CPU %x online: Create Rx thread\n", cpu);
+ FCOE_DBG("CPU %x online: Create Rx thread\n", cpu);
fcoe_percpu_thread_create(cpu);
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- FC_DBG("CPU %x offline: Remove Rx thread\n", cpu);
+ FCOE_DBG("CPU %x offline: Remove Rx thread\n", cpu);
fcoe_percpu_thread_destroy(cpu);
break;
default:
@@ -813,24 +847,21 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
lp = fc->ctlr.lp;
if (unlikely(lp == NULL)) {
- FC_DBG("cannot find hba structure");
+ FCOE_NETDEV_DBG(dev, "Cannot find hba structure");
goto err2;
}
if (!lp->link_up)
goto err2;
- if (unlikely(debug_fcoe)) {
- FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
- "end:%p sum:%d dev:%s", skb->len, skb->data_len,
- skb->head, skb->data, skb_tail_pointer(skb),
- skb_end_pointer(skb), skb->csum,
- skb->dev ? skb->dev->name : "<NULL>");
-
- }
+ FCOE_NETDEV_DBG(dev, "skb_info: len:%d data_len:%d head:%p "
+ "data:%p tail:%p end:%p sum:%d dev:%s",
+ skb->len, skb->data_len, skb->head, skb->data,
+ skb_tail_pointer(skb), skb_end_pointer(skb),
+ skb->csum, skb->dev ? skb->dev->name : "<NULL>");
/* check for FCOE packet type */
if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
- FC_DBG("wrong FC type frame");
+ FCOE_NETDEV_DBG(dev, "Wrong FC type frame");
goto err;
}
@@ -868,8 +899,9 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
* the first CPU now. For non-SMP systems this
* will check the same CPU twice.
*/
- FC_DBG("CPU is online, but no receive thread ready "
- "for incoming skb- using first online CPU.\n");
+ FCOE_NETDEV_DBG(dev, "CPU is online, but no receive thread "
+ "ready for incoming skb- using first online "
+ "CPU.\n");
spin_unlock_bh(&fps->fcoe_rx_list.lock);
cpu = first_cpu(cpu_online_map);
@@ -1168,19 +1200,17 @@ int fcoe_percpu_receive_thread(void *arg)
fr = fcoe_dev_from_skb(skb);
lp = fr->fr_dev;
if (unlikely(lp == NULL)) {
- FC_DBG("invalid HBA Structure");
+ FCOE_NETDEV_DBG(skb->dev, "Invalid HBA Structure");
kfree_skb(skb);
continue;
}
- if (unlikely(debug_fcoe)) {
- FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p "
- "tail:%p end:%p sum:%d dev:%s",
- skb->len, skb->data_len,
- skb->head, skb->data, skb_tail_pointer(skb),
- skb_end_pointer(skb), skb->csum,
- skb->dev ? skb->dev->name : "<NULL>");
- }
+ FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d "
+ "head:%p data:%p tail:%p end:%p sum:%d dev:%s",
+ skb->len, skb->data_len,
+ skb->head, skb->data, skb_tail_pointer(skb),
+ skb_end_pointer(skb), skb->csum,
+ skb->dev ? skb->dev->name : "<NULL>");
/*
* Save source MAC address before discarding header.
@@ -1200,7 +1230,7 @@ int fcoe_percpu_receive_thread(void *arg)
stats = fc_lport_get_stats(lp);
if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
if (stats->ErrorFrames < 5)
- printk(KERN_WARNING "FCoE version "
+ printk(KERN_WARNING "fcoe: FCoE version "
"mismatch: The frame has "
"version %x, but the "
"initiator supports version "
@@ -1253,7 +1283,7 @@ int fcoe_percpu_receive_thread(void *arg)
if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
if (le32_to_cpu(fr_crc(fp)) !=
~crc32(~0, skb->data, fr_len)) {
- if (debug_fcoe || stats->InvalidCRCCount < 5)
+ if (stats->InvalidCRCCount < 5)
printk(KERN_WARNING "fcoe: dropping "
"frame with CRC error\n");
stats->InvalidCRCCount++;
@@ -1399,7 +1429,8 @@ static int fcoe_device_notification(struct notifier_block *notifier,
case NETDEV_REGISTER:
break;
default:
- FC_DBG("Unknown event %ld from netdev netlink\n", event);
+ FCOE_NETDEV_DBG(real_dev, "Unknown event %ld "
+ "from netdev netlink\n", event);
}
if (link_possible && !fcoe_link_ok(lp))
fcoe_ctlr_link_up(&fc->ctlr);
@@ -1472,8 +1503,8 @@ static int fcoe_ethdrv_get(const struct net_device *netdev)
owner = fcoe_netdev_to_module_owner(netdev);
if (owner) {
- printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n",
- module_name(owner), netdev->name);
+ FCOE_NETDEV_DBG(netdev, "Hold driver module %s\n",
+ module_name(owner));
return try_module_get(owner);
}
return -ENODEV;
@@ -1494,8 +1525,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
owner = fcoe_netdev_to_module_owner(netdev);
if (owner) {
- printk(KERN_DEBUG "fcoe:release driver module %s for %s\n",
- module_name(owner), netdev->name);
+ FCOE_NETDEV_DBG(netdev, "Release driver module %s\n",
+ module_name(owner));
module_put(owner);
return 0;
}
@@ -1526,7 +1557,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
}
rc = fcoe_if_destroy(netdev);
if (rc) {
- printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n",
+ printk(KERN_ERR "fcoe: Failed to destroy interface (%s)\n",
netdev->name);
rc = -EIO;
goto out_putdev;
@@ -1565,7 +1596,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
rc = fcoe_if_create(netdev);
if (rc) {
- printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n",
+ printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
netdev->name);
fcoe_ethdrv_put(netdev);
rc = -EIO;