aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe
diff options
context:
space:
mode:
authorChris Leech <christopher.leech@intel.com>2009-08-25 17:00:23 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-09-10 13:07:38 -0400
commit2e70e2415193b84c1b79ec373af15c3f280ad7c4 (patch)
tree84799295b00350f3fa33ca3becd7511d07e97791 /drivers/scsi/fcoe
parentc863df33bb784eecfb24090d2258fa0d3f653750 (diff)
[SCSI] fcoe: Fix module ref count bug by adding NETDEV UNREGISTER handling
Fixes reference counting on fcoe_instance and net_device, and adds NETDEV_UNREGISTER notifier handling so that you can unload network drivers. FCoE no longer increments the module use count for the network driver. On an NETDEV_UNREGISTER event, destroying the FCoE instance is deferred to a workqueue context to avoid RTNL deadlocks. Based in part by an earlier patch from John Fastabend John's patch description: Currently, the netdev module ref count is not decremented with module_put() when the module is unloaded while fcoe instances are present. To fix this removed reference count on netdev module completely and added functionality to netdev event handling for NETDEV_UNREGISTER events. This allows fcoe to remove devices cleanly when the netdev module is unloaded so we no longer need to hold a reference count for the netdev module. Signed-off-by: Chris Leech <christopher.leech@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r--drivers/scsi/fcoe/fcoe.c186
-rw-r--r--drivers/scsi/fcoe/fcoe.h2
2 files changed, 67 insertions, 121 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c9a0346e493..c0264a98439 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -74,12 +74,13 @@ static int fcoe_link_ok(struct fc_lport *lp);
74 74
75static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); 75static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
76static int fcoe_hostlist_add(const struct fc_lport *); 76static int fcoe_hostlist_add(const struct fc_lport *);
77static int fcoe_hostlist_remove(const struct fc_lport *);
78 77
79static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *); 78static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
80static int fcoe_device_notification(struct notifier_block *, ulong, void *); 79static int fcoe_device_notification(struct notifier_block *, ulong, void *);
81static void fcoe_dev_setup(void); 80static void fcoe_dev_setup(void);
82static void fcoe_dev_cleanup(void); 81static void fcoe_dev_cleanup(void);
82static struct fcoe_interface *
83 fcoe_hostlist_lookup_port(const struct net_device *dev);
83 84
84/* notification function from net device */ 85/* notification function from net device */
85static struct notifier_block fcoe_notifier = { 86static struct notifier_block fcoe_notifier = {
@@ -149,6 +150,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
149 * @netdev : ptr to the associated netdevice struct 150 * @netdev : ptr to the associated netdevice struct
150 * 151 *
151 * Returns : 0 for success 152 * Returns : 0 for success
153 * Locking: must be called with the RTNL mutex held
152 */ 154 */
153static int fcoe_interface_setup(struct fcoe_interface *fcoe, 155static int fcoe_interface_setup(struct fcoe_interface *fcoe,
154 struct net_device *netdev) 156 struct net_device *netdev)
@@ -188,13 +190,11 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
188 * or enter promiscuous mode if not capable of listening 190 * or enter promiscuous mode if not capable of listening
189 * for multiple unicast MACs. 191 * for multiple unicast MACs.
190 */ 192 */
191 rtnl_lock();
192 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 193 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
193 dev_unicast_add(netdev, flogi_maddr); 194 dev_unicast_add(netdev, flogi_maddr);
194 if (fip->spma) 195 if (fip->spma)
195 dev_unicast_add(netdev, fip->ctl_src_addr); 196 dev_unicast_add(netdev, fip->ctl_src_addr);
196 dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); 197 dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
197 rtnl_unlock();
198 198
199 /* 199 /*
200 * setup the receive function from ethernet driver 200 * setup the receive function from ethernet driver
@@ -215,6 +215,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
215 215
216static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); 216static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
217static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new); 217static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new);
218static void fcoe_destroy_work(struct work_struct *work);
218 219
219/** 220/**
220 * fcoe_interface_create() 221 * fcoe_interface_create()
@@ -232,6 +233,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
232 return NULL; 233 return NULL;
233 } 234 }
234 235
236 dev_hold(netdev);
235 kref_init(&fcoe->kref); 237 kref_init(&fcoe->kref);
236 238
237 /* 239 /*
@@ -249,6 +251,8 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
249/** 251/**
250 * fcoe_interface_cleanup() - clean up netdev configurations 252 * fcoe_interface_cleanup() - clean up netdev configurations
251 * @fcoe: 253 * @fcoe:
254 *
255 * Caller must be holding the RTNL mutex
252 */ 256 */
253void fcoe_interface_cleanup(struct fcoe_interface *fcoe) 257void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
254{ 258{
@@ -266,11 +270,7 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
266 __dev_remove_pack(&fcoe->fip_packet_type); 270 __dev_remove_pack(&fcoe->fip_packet_type);
267 synchronize_net(); 271 synchronize_net();
268 272
269 /* tear-down the FCoE controller */
270 fcoe_ctlr_destroy(&fcoe->ctlr);
271
272 /* Delete secondary MAC addresses */ 273 /* Delete secondary MAC addresses */
273 rtnl_lock();
274 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 274 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
275 dev_unicast_delete(netdev, flogi_maddr); 275 dev_unicast_delete(netdev, flogi_maddr);
276 if (!is_zero_ether_addr(fip->data_src_addr)) 276 if (!is_zero_ether_addr(fip->data_src_addr))
@@ -278,7 +278,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
278 if (fip->spma) 278 if (fip->spma)
279 dev_unicast_delete(netdev, fip->ctl_src_addr); 279 dev_unicast_delete(netdev, fip->ctl_src_addr);
280 dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); 280 dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
281 rtnl_unlock();
282} 281}
283 282
284/** 283/**
@@ -288,10 +287,14 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
288static void fcoe_interface_release(struct kref *kref) 287static void fcoe_interface_release(struct kref *kref)
289{ 288{
290 struct fcoe_interface *fcoe; 289 struct fcoe_interface *fcoe;
290 struct net_device *netdev;
291 291
292 fcoe = container_of(kref, struct fcoe_interface, kref); 292 fcoe = container_of(kref, struct fcoe_interface, kref);
293 fcoe_interface_cleanup(fcoe); 293 netdev = fcoe->netdev;
294 /* tear-down the FCoE controller */
295 fcoe_ctlr_destroy(&fcoe->ctlr);
294 kfree(fcoe); 296 kfree(fcoe);
297 dev_put(netdev);
295} 298}
296 299
297/** 300/**
@@ -642,8 +645,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
642 /* Free memory used by statistical counters */ 645 /* Free memory used by statistical counters */
643 fc_lport_free_stats(lport); 646 fc_lport_free_stats(lport);
644 647
645 /* Release the net_device and Scsi_Host */ 648 /* Release the Scsi_Host */
646 dev_put(netdev);
647 scsi_host_put(lport->host); 649 scsi_host_put(lport->host);
648} 650}
649 651
@@ -718,7 +720,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
718 } 720 }
719 lport = shost_priv(shost); 721 lport = shost_priv(shost);
720 port = lport_priv(lport); 722 port = lport_priv(lport);
723 port->lport = lport;
721 port->fcoe = fcoe; 724 port->fcoe = fcoe;
725 INIT_WORK(&port->destroy_work, fcoe_destroy_work);
722 726
723 /* configure fc_lport, e.g., em */ 727 /* configure fc_lport, e.g., em */
724 rc = fcoe_lport_config(lport); 728 rc = fcoe_lport_config(lport);
@@ -769,7 +773,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
769 goto out_lp_destroy; 773 goto out_lp_destroy;
770 } 774 }
771 775
772 dev_hold(netdev);
773 fcoe_interface_get(fcoe); 776 fcoe_interface_get(fcoe);
774 return lport; 777 return lport;
775 778
@@ -1530,19 +1533,19 @@ static int fcoe_device_notification(struct notifier_block *notifier,
1530 struct fc_lport *lp = NULL; 1533 struct fc_lport *lp = NULL;
1531 struct net_device *netdev = ptr; 1534 struct net_device *netdev = ptr;
1532 struct fcoe_interface *fcoe; 1535 struct fcoe_interface *fcoe;
1536 struct fcoe_port *port;
1533 struct fcoe_dev_stats *stats; 1537 struct fcoe_dev_stats *stats;
1534 u32 link_possible = 1; 1538 u32 link_possible = 1;
1535 u32 mfs; 1539 u32 mfs;
1536 int rc = NOTIFY_OK; 1540 int rc = NOTIFY_OK;
1537 1541
1538 read_lock(&fcoe_hostlist_lock); 1542 write_lock(&fcoe_hostlist_lock);
1539 list_for_each_entry(fcoe, &fcoe_hostlist, list) { 1543 list_for_each_entry(fcoe, &fcoe_hostlist, list) {
1540 if (fcoe->netdev == netdev) { 1544 if (fcoe->netdev == netdev) {
1541 lp = fcoe->ctlr.lp; 1545 lp = fcoe->ctlr.lp;
1542 break; 1546 break;
1543 } 1547 }
1544 } 1548 }
1545 read_unlock(&fcoe_hostlist_lock);
1546 if (lp == NULL) { 1549 if (lp == NULL) {
1547 rc = NOTIFY_DONE; 1550 rc = NOTIFY_DONE;
1548 goto out; 1551 goto out;
@@ -1564,6 +1567,13 @@ static int fcoe_device_notification(struct notifier_block *notifier,
1564 break; 1567 break;
1565 case NETDEV_REGISTER: 1568 case NETDEV_REGISTER:
1566 break; 1569 break;
1570 case NETDEV_UNREGISTER:
1571 list_del(&fcoe->list);
1572 port = lport_priv(fcoe->ctlr.lp);
1573 fcoe_interface_cleanup(fcoe);
1574 schedule_work(&port->destroy_work);
1575 goto out;
1576 break;
1567 default: 1577 default:
1568 FCOE_NETDEV_DBG(netdev, "Unknown event %ld " 1578 FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
1569 "from netdev netlink\n", event); 1579 "from netdev netlink\n", event);
@@ -1576,6 +1586,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
1576 fcoe_clean_pending_queue(lp); 1586 fcoe_clean_pending_queue(lp);
1577 } 1587 }
1578out: 1588out:
1589 write_unlock(&fcoe_hostlist_lock);
1579 return rc; 1590 return rc;
1580} 1591}
1581 1592
@@ -1601,75 +1612,6 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
1601} 1612}
1602 1613
1603/** 1614/**
1604 * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev
1605 * @netdev: the target netdev
1606 *
1607 * Returns: ptr to the struct module, NULL for failure
1608 */
1609static struct module *
1610fcoe_netdev_to_module_owner(const struct net_device *netdev)
1611{
1612 struct device *dev;
1613
1614 if (!netdev)
1615 return NULL;
1616
1617 dev = netdev->dev.parent;
1618 if (!dev)
1619 return NULL;
1620
1621 if (!dev->driver)
1622 return NULL;
1623
1624 return dev->driver->owner;
1625}
1626
1627/**
1628 * fcoe_ethdrv_get() - Hold the Ethernet driver
1629 * @netdev: the target netdev
1630 *
1631 * Holds the Ethernet driver module by try_module_get() for
1632 * the corresponding netdev.
1633 *
1634 * Returns: 0 for success
1635 */
1636static int fcoe_ethdrv_get(const struct net_device *netdev)
1637{
1638 struct module *owner;
1639
1640 owner = fcoe_netdev_to_module_owner(netdev);
1641 if (owner) {
1642 FCOE_NETDEV_DBG(netdev, "Hold driver module %s\n",
1643 module_name(owner));
1644 return try_module_get(owner);
1645 }
1646 return -ENODEV;
1647}
1648
1649/**
1650 * fcoe_ethdrv_put() - Release the Ethernet driver
1651 * @netdev: the target netdev
1652 *
1653 * Releases the Ethernet driver module by module_put for
1654 * the corresponding netdev.
1655 *
1656 * Returns: 0 for success
1657 */
1658static int fcoe_ethdrv_put(const struct net_device *netdev)
1659{
1660 struct module *owner;
1661
1662 owner = fcoe_netdev_to_module_owner(netdev);
1663 if (owner) {
1664 FCOE_NETDEV_DBG(netdev, "Release driver module %s\n",
1665 module_name(owner));
1666 module_put(owner);
1667 return 0;
1668 }
1669 return -ENODEV;
1670}
1671
1672/**
1673 * fcoe_destroy() - handles the destroy from sysfs 1615 * fcoe_destroy() - handles the destroy from sysfs
1674 * @buffer: expected to be an eth if name 1616 * @buffer: expected to be an eth if name
1675 * @kp: associated kernel param 1617 * @kp: associated kernel param
@@ -1678,10 +1620,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev)
1678 */ 1620 */
1679static int fcoe_destroy(const char *buffer, struct kernel_param *kp) 1621static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
1680{ 1622{
1681 struct net_device *netdev;
1682 struct fcoe_interface *fcoe; 1623 struct fcoe_interface *fcoe;
1683 struct fcoe_port *port; 1624 struct net_device *netdev;
1684 struct fc_lport *lport;
1685 int rc; 1625 int rc;
1686 1626
1687 mutex_lock(&fcoe_config_mutex); 1627 mutex_lock(&fcoe_config_mutex);
@@ -1702,19 +1642,20 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
1702 rc = -ENODEV; 1642 rc = -ENODEV;
1703 goto out_nodev; 1643 goto out_nodev;
1704 } 1644 }
1705 /* look for existing lport */ 1645
1706 lport = fcoe_hostlist_lookup(netdev); 1646 write_lock(&fcoe_hostlist_lock);
1707 if (!lport) { 1647 fcoe = fcoe_hostlist_lookup_port(netdev);
1648 if (!fcoe) {
1649 write_unlock(&fcoe_hostlist_lock);
1708 rc = -ENODEV; 1650 rc = -ENODEV;
1709 goto out_putdev; 1651 goto out_putdev;
1710 } 1652 }
1711 /* Remove the instance from fcoe's list */ 1653 list_del(&fcoe->list);
1712 fcoe_hostlist_remove(lport); 1654 write_unlock(&fcoe_hostlist_lock);
1713 port = lport_priv(lport); 1655 rtnl_lock();
1714 fcoe = port->fcoe; 1656 fcoe_interface_cleanup(fcoe);
1715 fcoe_if_destroy(lport); 1657 rtnl_unlock();
1716 fcoe_ethdrv_put(netdev); 1658 fcoe_if_destroy(fcoe->ctlr.lp);
1717 rc = 0;
1718out_putdev: 1659out_putdev:
1719 dev_put(netdev); 1660 dev_put(netdev);
1720out_nodev: 1661out_nodev:
@@ -1722,6 +1663,16 @@ out_nodev:
1722 return rc; 1663 return rc;
1723} 1664}
1724 1665
1666static void fcoe_destroy_work(struct work_struct *work)
1667{
1668 struct fcoe_port *port;
1669
1670 port = container_of(work, struct fcoe_port, destroy_work);
1671 mutex_lock(&fcoe_config_mutex);
1672 fcoe_if_destroy(port->lport);
1673 mutex_unlock(&fcoe_config_mutex);
1674}
1675
1725/** 1676/**
1726 * fcoe_create() - Handles the create call from sysfs 1677 * fcoe_create() - Handles the create call from sysfs
1727 * @buffer: expected to be an eth if name 1678 * @buffer: expected to be an eth if name
@@ -1749,17 +1700,18 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
1749 } 1700 }
1750#endif 1701#endif
1751 1702
1703 rtnl_lock();
1752 netdev = fcoe_if_to_netdev(buffer); 1704 netdev = fcoe_if_to_netdev(buffer);
1753 if (!netdev) { 1705 if (!netdev) {
1754 rc = -ENODEV; 1706 rc = -ENODEV;
1755 goto out_nodev; 1707 goto out_nodev;
1756 } 1708 }
1709
1757 /* look for existing lport */ 1710 /* look for existing lport */
1758 if (fcoe_hostlist_lookup(netdev)) { 1711 if (fcoe_hostlist_lookup(netdev)) {
1759 rc = -EEXIST; 1712 rc = -EEXIST;
1760 goto out_putdev; 1713 goto out_putdev;
1761 } 1714 }
1762 fcoe_ethdrv_get(netdev);
1763 1715
1764 fcoe = fcoe_interface_create(netdev); 1716 fcoe = fcoe_interface_create(netdev);
1765 if (!fcoe) { 1717 if (!fcoe) {
@@ -1771,8 +1723,8 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
1771 if (IS_ERR(lport)) { 1723 if (IS_ERR(lport)) {
1772 printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", 1724 printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
1773 netdev->name); 1725 netdev->name);
1774 fcoe_ethdrv_put(netdev);
1775 rc = -EIO; 1726 rc = -EIO;
1727 fcoe_interface_cleanup(fcoe);
1776 goto out_free; 1728 goto out_free;
1777 } 1729 }
1778 1730
@@ -1798,6 +1750,7 @@ out_free:
1798out_putdev: 1750out_putdev:
1799 dev_put(netdev); 1751 dev_put(netdev);
1800out_nodev: 1752out_nodev:
1753 rtnl_unlock();
1801 mutex_unlock(&fcoe_config_mutex); 1754 mutex_unlock(&fcoe_config_mutex);
1802 return rc; 1755 return rc;
1803} 1756}
@@ -1973,25 +1926,6 @@ int fcoe_hostlist_add(const struct fc_lport *lport)
1973} 1926}
1974 1927
1975/** 1928/**
1976 * fcoe_hostlist_remove() - remove a lport from lports list
1977 * @lp: ptr to the fc_lport to be removed
1978 *
1979 * Returns: 0 for success
1980 */
1981int fcoe_hostlist_remove(const struct fc_lport *lport)
1982{
1983 struct fcoe_interface *fcoe;
1984
1985 write_lock_bh(&fcoe_hostlist_lock);
1986 fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
1987 BUG_ON(!fcoe);
1988 list_del(&fcoe->list);
1989 write_unlock_bh(&fcoe_hostlist_lock);
1990
1991 return 0;
1992}
1993
1994/**
1995 * fcoe_init() - fcoe module loading initialization 1929 * fcoe_init() - fcoe module loading initialization
1996 * 1930 *
1997 * Returns 0 on success, negative on failure 1931 * Returns 0 on success, negative on failure
@@ -2046,6 +1980,7 @@ static void __exit fcoe_exit(void)
2046 unsigned int cpu; 1980 unsigned int cpu;
2047 struct fcoe_interface *fcoe, *tmp; 1981 struct fcoe_interface *fcoe, *tmp;
2048 LIST_HEAD(local_list); 1982 LIST_HEAD(local_list);
1983 struct fcoe_port *port;
2049 1984
2050 mutex_lock(&fcoe_config_mutex); 1985 mutex_lock(&fcoe_config_mutex);
2051 1986
@@ -2058,7 +1993,11 @@ static void __exit fcoe_exit(void)
2058 1993
2059 list_for_each_entry_safe(fcoe, tmp, &local_list, list) { 1994 list_for_each_entry_safe(fcoe, tmp, &local_list, list) {
2060 list_del(&fcoe->list); 1995 list_del(&fcoe->list);
2061 fcoe_if_destroy(fcoe->ctlr.lp); 1996 port = lport_priv(fcoe->ctlr.lp);
1997 rtnl_lock();
1998 fcoe_interface_cleanup(fcoe);
1999 rtnl_unlock();
2000 schedule_work(&port->destroy_work);
2062 } 2001 }
2063 2002
2064 unregister_hotcpu_notifier(&fcoe_cpu_notifier); 2003 unregister_hotcpu_notifier(&fcoe_cpu_notifier);
@@ -2066,9 +2005,14 @@ static void __exit fcoe_exit(void)
2066 for_each_online_cpu(cpu) 2005 for_each_online_cpu(cpu)
2067 fcoe_percpu_thread_destroy(cpu); 2006 fcoe_percpu_thread_destroy(cpu);
2068 2007
2069 /* detach from scsi transport */
2070 fcoe_if_exit();
2071
2072 mutex_unlock(&fcoe_config_mutex); 2008 mutex_unlock(&fcoe_config_mutex);
2009
2010 /* flush any asyncronous interface destroys,
2011 * this should happen after the netdev notifier is unregistered */
2012 flush_scheduled_work();
2013
2014 /* detach from scsi transport
2015 * must happen after all destroys are done, therefor after the flush */
2016 fcoe_if_exit();
2073} 2017}
2074module_exit(fcoe_exit); 2018module_exit(fcoe_exit);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index ff229288b7f..ce7f60fb1bc 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -93,9 +93,11 @@ struct fcoe_interface {
93 */ 93 */
94struct fcoe_port { 94struct fcoe_port {
95 struct fcoe_interface *fcoe; 95 struct fcoe_interface *fcoe;
96 struct fc_lport *lport;
96 struct sk_buff_head fcoe_pending_queue; 97 struct sk_buff_head fcoe_pending_queue;
97 u8 fcoe_pending_queue_active; 98 u8 fcoe_pending_queue_active;
98 struct timer_list timer; /* queue timer */ 99 struct timer_list timer; /* queue timer */
100 struct work_struct destroy_work; /* to prevent rtnl deadlocks */
99}; 101};
100 102
101#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) 103#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)