diff options
-rw-r--r-- | drivers/scsi/fcoe/fcoe_transport.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index 745eb9a22d64..258684101bfd 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); | |||
39 | static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); | 39 | static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); |
40 | static int fcoe_transport_enable(const char *, struct kernel_param *); | 40 | static int fcoe_transport_enable(const char *, struct kernel_param *); |
41 | static int fcoe_transport_disable(const char *, struct kernel_param *); | 41 | static int fcoe_transport_disable(const char *, struct kernel_param *); |
42 | static int libfcoe_device_notification(struct notifier_block *notifier, | ||
43 | ulong event, void *ptr); | ||
42 | 44 | ||
43 | static LIST_HEAD(fcoe_transports); | 45 | static LIST_HEAD(fcoe_transports); |
44 | static LIST_HEAD(fcoe_netdevs); | ||
45 | static DEFINE_MUTEX(ft_mutex); | 46 | static DEFINE_MUTEX(ft_mutex); |
47 | static LIST_HEAD(fcoe_netdevs); | ||
48 | static DEFINE_MUTEX(fn_mutex); | ||
46 | 49 | ||
47 | unsigned int libfcoe_debug_logging; | 50 | unsigned int libfcoe_debug_logging; |
48 | module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); | 51 | module_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"); |
76 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); | 79 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); |
77 | 80 | ||
81 | /* notification function for packets from net device */ | ||
82 | static 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 | ||
376 | static int __init fcoe_transport_init(void) | 384 | static 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 | */ | ||
500 | static 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 |