aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/fcoe/fcoe_transport.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index 745eb9a22d6..258684101bf 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -39,10 +39,13 @@ static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
39static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); 39static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
40static int fcoe_transport_enable(const char *, struct kernel_param *); 40static int fcoe_transport_enable(const char *, struct kernel_param *);
41static int fcoe_transport_disable(const char *, struct kernel_param *); 41static int fcoe_transport_disable(const char *, struct kernel_param *);
42static int libfcoe_device_notification(struct notifier_block *notifier,
43 ulong event, void *ptr);
42 44
43static LIST_HEAD(fcoe_transports); 45static LIST_HEAD(fcoe_transports);
44static LIST_HEAD(fcoe_netdevs);
45static DEFINE_MUTEX(ft_mutex); 46static DEFINE_MUTEX(ft_mutex);
47static LIST_HEAD(fcoe_netdevs);
48static DEFINE_MUTEX(fn_mutex);
46 49
47unsigned int libfcoe_debug_logging; 50unsigned int libfcoe_debug_logging;
48module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); 51module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
@@ -75,6 +78,11 @@ module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
75__MODULE_PARM_TYPE(disable, "string"); 78__MODULE_PARM_TYPE(disable, "string");
76MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); 79MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
77 80
81/* notification function for packets from net device */
82static struct notifier_block libfcoe_notifier = {
83 .notifier_call = libfcoe_device_notification,
84};
85
78/** 86/**
79 * fcoe_fc_crc() - Calculates the CRC for a given frame 87 * fcoe_fc_crc() - Calculates the CRC for a given frame
80 * @fp: The frame to be checksumed 88 * @fp: The frame to be checksumed
@@ -375,6 +383,7 @@ static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
375 383
376static int __init fcoe_transport_init(void) 384static int __init fcoe_transport_init(void)
377{ 385{
386 register_netdevice_notifier(&libfcoe_notifier);
378 return 0; 387 return 0;
379} 388}
380 389
@@ -382,6 +391,7 @@ static int __exit fcoe_transport_exit(void)
382{ 391{
383 struct fcoe_transport *ft; 392 struct fcoe_transport *ft;
384 393
394 unregister_netdevice_notifier(&libfcoe_notifier);
385 mutex_lock(&ft_mutex); 395 mutex_lock(&ft_mutex);
386 list_for_each_entry(ft, &fcoe_transports, list) 396 list_for_each_entry(ft, &fcoe_transports, list)
387 printk(KERN_ERR "FCoE transport %s is still attached!\n", 397 printk(KERN_ERR "FCoE transport %s is still attached!\n",
@@ -405,7 +415,9 @@ static int fcoe_add_netdev_mapping(struct net_device *netdev,
405 nm->netdev = netdev; 415 nm->netdev = netdev;
406 nm->ft = ft; 416 nm->ft = ft;
407 417
418 mutex_lock(&fn_mutex);
408 list_add(&nm->list, &fcoe_netdevs); 419 list_add(&nm->list, &fcoe_netdevs);
420 mutex_unlock(&fn_mutex);
409 return 0; 421 return 0;
410} 422}
411 423
@@ -414,13 +426,16 @@ static void fcoe_del_netdev_mapping(struct net_device *netdev)
414{ 426{
415 struct fcoe_netdev_mapping *nm = NULL, *tmp; 427 struct fcoe_netdev_mapping *nm = NULL, *tmp;
416 428
429 mutex_lock(&fn_mutex);
417 list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { 430 list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
418 if (nm->netdev == netdev) { 431 if (nm->netdev == netdev) {
419 list_del(&nm->list); 432 list_del(&nm->list);
420 kfree(nm); 433 kfree(nm);
434 mutex_unlock(&fn_mutex);
421 return; 435 return;
422 } 436 }
423 } 437 }
438 mutex_unlock(&fn_mutex);
424} 439}
425 440
426 441
@@ -438,13 +453,16 @@ static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
438 struct fcoe_transport *ft = NULL; 453 struct fcoe_transport *ft = NULL;
439 struct fcoe_netdev_mapping *nm; 454 struct fcoe_netdev_mapping *nm;
440 455
456 mutex_lock(&fn_mutex);
441 list_for_each_entry(nm, &fcoe_netdevs, list) { 457 list_for_each_entry(nm, &fcoe_netdevs, list) {
442 if (netdev == nm->netdev) { 458 if (netdev == nm->netdev) {
443 ft = nm->ft; 459 ft = nm->ft;
460 mutex_unlock(&fn_mutex);
444 return ft; 461 return ft;
445 } 462 }
446 } 463 }
447 464
465 mutex_unlock(&fn_mutex);
448 return NULL; 466 return NULL;
449} 467}
450 468
@@ -470,6 +488,32 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
470} 488}
471 489
472/** 490/**
491 * libfcoe_device_notification() - Handler for net device events
492 * @notifier: The context of the notification
493 * @event: The type of event
494 * @ptr: The net device that the event was on
495 *
496 * This function is called by the Ethernet driver in case of link change event.
497 *
498 * Returns: 0 for success
499 */
500static int libfcoe_device_notification(struct notifier_block *notifier,
501 ulong event, void *ptr)
502{
503 struct net_device *netdev = ptr;
504
505 switch (event) {
506 case NETDEV_UNREGISTER:
507 printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n",
508 netdev->name);
509 fcoe_del_netdev_mapping(netdev);
510 break;
511 }
512 return NOTIFY_OK;
513}
514
515
516/**
473 * fcoe_transport_create() - Create a fcoe interface 517 * fcoe_transport_create() - Create a fcoe interface
474 * @buffer: The name of the Ethernet interface to create on 518 * @buffer: The name of the Ethernet interface to create on
475 * @kp: The associated kernel param 519 * @kp: The associated kernel param