static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
static int fcoe_transport_enable(const char *, struct kernel_param *);
static int fcoe_transport_disable(const char *, struct kernel_param *);
+static int libfcoe_device_notification(struct notifier_block *notifier,
+ ulong event, void *ptr);
static LIST_HEAD(fcoe_transports);
-static LIST_HEAD(fcoe_netdevs);
static DEFINE_MUTEX(ft_mutex);
+static LIST_HEAD(fcoe_netdevs);
+static DEFINE_MUTEX(fn_mutex);
unsigned int libfcoe_debug_logging;
module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
__MODULE_PARM_TYPE(disable, "string");
MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
+/* notification function for packets from net device */
+static struct notifier_block libfcoe_notifier = {
+ .notifier_call = libfcoe_device_notification,
+};
+
/**
* fcoe_fc_crc() - Calculates the CRC for a given frame
* @fp: The frame to be checksumed
static int __init fcoe_transport_init(void)
{
+ register_netdevice_notifier(&libfcoe_notifier);
return 0;
}
{
struct fcoe_transport *ft;
+ unregister_netdevice_notifier(&libfcoe_notifier);
mutex_lock(&ft_mutex);
list_for_each_entry(ft, &fcoe_transports, list)
printk(KERN_ERR "FCoE transport %s is still attached!\n",
nm->netdev = netdev;
nm->ft = ft;
+ mutex_lock(&fn_mutex);
list_add(&nm->list, &fcoe_netdevs);
+ mutex_unlock(&fn_mutex);
return 0;
}
{
struct fcoe_netdev_mapping *nm = NULL, *tmp;
+ mutex_lock(&fn_mutex);
list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
if (nm->netdev == netdev) {
list_del(&nm->list);
kfree(nm);
+ mutex_unlock(&fn_mutex);
return;
}
}
+ mutex_unlock(&fn_mutex);
}
struct fcoe_transport *ft = NULL;
struct fcoe_netdev_mapping *nm;
+ mutex_lock(&fn_mutex);
list_for_each_entry(nm, &fcoe_netdevs, list) {
if (netdev == nm->netdev) {
ft = nm->ft;
+ mutex_unlock(&fn_mutex);
return ft;
}
}
+ mutex_unlock(&fn_mutex);
return NULL;
}
return NULL;
}
+/**
+ * libfcoe_device_notification() - Handler for net device events
+ * @notifier: The context of the notification
+ * @event: The type of event
+ * @ptr: The net device that the event was on
+ *
+ * This function is called by the Ethernet driver in case of link change event.
+ *
+ * Returns: 0 for success
+ */
+static int libfcoe_device_notification(struct notifier_block *notifier,
+ ulong event, void *ptr)
+{
+ struct net_device *netdev = ptr;
+
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n",
+ netdev->name);
+ fcoe_del_netdev_mapping(netdev);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+
/**
* fcoe_transport_create() - Create a fcoe interface
* @buffer: The name of the Ethernet interface to create on