aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe_transport.c
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2011-02-25 18:03:17 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-28 19:33:46 -0500
commit70be6344ea1ad9110a5b422aeab47a3fbb01ba7f (patch)
treea0432b0fcd56a708f81d1d680dba264dbddc7f72 /drivers/scsi/fcoe/fcoe_transport.c
parentf4d2b2b6ea8abd0df72a31b4724522a277af6a6c (diff)
[SCSI] libfcoe: Remove stale fcoe-netdev entries
When L2 driver is unloaded, libfcoe_destroy tries to access the fcoe transport structure matching the netdev. However, since the netdev is unregistered by that time, it fails to do so. Hence the stale mappings exists in the fcoe-netdev list. Handle NETDEV_UREGISTER device notification mechanism to remove the stale fcoe-netdev mapping. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.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/fcoe_transport.c')
-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 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);
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