aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2009-08-14 11:49:44 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-15 21:50:43 -0400
commita3059b12adae868c42629ecf058a94195ef1e958 (patch)
treed736fb5260aaf71d36d8b066b04db00135c4e605 /drivers/net
parent64c6460875957502541a4ba30835ac625a0bee79 (diff)
cnic: Refine registration with bnx2.
Register and unregister with bnx2 during NETDEV_UP and NETDEV_DOWN events. This simplifies the sequence of events and allows locking fixes in the next patch. Signed-off-by: Michael Chan <mchan@broadcom.com> Reviewed-by: Benjamin Li <benli@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/cnic.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index ecde186fccd6..2db81f0e4f72 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2393,21 +2393,45 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
2393 return 0; 2393 return 0;
2394} 2394}
2395 2395
2396static int cnic_start_hw(struct cnic_dev *dev) 2396static int cnic_register_netdev(struct cnic_dev *dev)
2397{ 2397{
2398 struct cnic_local *cp = dev->cnic_priv; 2398 struct cnic_local *cp = dev->cnic_priv;
2399 struct cnic_eth_dev *ethdev = cp->ethdev; 2399 struct cnic_eth_dev *ethdev = cp->ethdev;
2400 int err; 2400 int err;
2401 2401
2402 if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) 2402 if (!ethdev)
2403 return -EALREADY; 2403 return -ENODEV;
2404
2405 if (ethdev->drv_state & CNIC_DRV_STATE_REGD)
2406 return 0;
2404 2407
2405 err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev); 2408 err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev);
2406 if (err) { 2409 if (err)
2407 printk(KERN_ERR PFX "%s: register_cnic failed\n", 2410 printk(KERN_ERR PFX "%s: register_cnic failed\n",
2408 dev->netdev->name); 2411 dev->netdev->name);
2409 goto err2; 2412
2410 } 2413 return err;
2414}
2415
2416static void cnic_unregister_netdev(struct cnic_dev *dev)
2417{
2418 struct cnic_local *cp = dev->cnic_priv;
2419 struct cnic_eth_dev *ethdev = cp->ethdev;
2420
2421 if (!ethdev)
2422 return;
2423
2424 ethdev->drv_unregister_cnic(dev->netdev);
2425}
2426
2427static int cnic_start_hw(struct cnic_dev *dev)
2428{
2429 struct cnic_local *cp = dev->cnic_priv;
2430 struct cnic_eth_dev *ethdev = cp->ethdev;
2431 int err;
2432
2433 if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
2434 return -EALREADY;
2411 2435
2412 dev->regview = ethdev->io_base; 2436 dev->regview = ethdev->io_base;
2413 cp->chip_id = ethdev->chip_id; 2437 cp->chip_id = ethdev->chip_id;
@@ -2438,18 +2462,13 @@ static int cnic_start_hw(struct cnic_dev *dev)
2438 return 0; 2462 return 0;
2439 2463
2440err1: 2464err1:
2441 ethdev->drv_unregister_cnic(dev->netdev);
2442 cp->free_resc(dev); 2465 cp->free_resc(dev);
2443 pci_dev_put(dev->pcidev); 2466 pci_dev_put(dev->pcidev);
2444err2:
2445 return err; 2467 return err;
2446} 2468}
2447 2469
2448static void cnic_stop_bnx2_hw(struct cnic_dev *dev) 2470static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
2449{ 2471{
2450 struct cnic_local *cp = dev->cnic_priv;
2451 struct cnic_eth_dev *ethdev = cp->ethdev;
2452
2453 cnic_disable_bnx2_int_sync(dev); 2472 cnic_disable_bnx2_int_sync(dev);
2454 2473
2455 cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0); 2474 cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
@@ -2461,8 +2480,6 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
2461 cnic_setup_5709_context(dev, 0); 2480 cnic_setup_5709_context(dev, 0);
2462 cnic_free_irq(dev); 2481 cnic_free_irq(dev);
2463 2482
2464 ethdev->drv_unregister_cnic(dev->netdev);
2465
2466 cnic_free_resc(dev); 2483 cnic_free_resc(dev);
2467} 2484}
2468 2485
@@ -2646,6 +2663,10 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
2646 else if (event == NETDEV_UNREGISTER) 2663 else if (event == NETDEV_UNREGISTER)
2647 cnic_ulp_exit(dev); 2664 cnic_ulp_exit(dev);
2648 else if (event == NETDEV_UP) { 2665 else if (event == NETDEV_UP) {
2666 if (cnic_register_netdev(dev) != 0) {
2667 cnic_put(dev);
2668 goto done;
2669 }
2649 mutex_lock(&cnic_lock); 2670 mutex_lock(&cnic_lock);
2650 if (!cnic_start_hw(dev)) 2671 if (!cnic_start_hw(dev))
2651 cnic_ulp_start(dev); 2672 cnic_ulp_start(dev);
@@ -2672,6 +2693,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
2672 cnic_ulp_stop(dev); 2693 cnic_ulp_stop(dev);
2673 cnic_stop_hw(dev); 2694 cnic_stop_hw(dev);
2674 mutex_unlock(&cnic_lock); 2695 mutex_unlock(&cnic_lock);
2696 cnic_unregister_netdev(dev);
2675 } else if (event == NETDEV_UNREGISTER) { 2697 } else if (event == NETDEV_UNREGISTER) {
2676 write_lock(&cnic_dev_lock); 2698 write_lock(&cnic_dev_lock);
2677 list_del_init(&dev->list); 2699 list_del_init(&dev->list);
@@ -2703,6 +2725,7 @@ static void cnic_release(void)
2703 } 2725 }
2704 2726
2705 cnic_ulp_exit(dev); 2727 cnic_ulp_exit(dev);
2728 cnic_unregister_netdev(dev);
2706 list_del_init(&dev->list); 2729 list_del_init(&dev->list);
2707 cnic_free_dev(dev); 2730 cnic_free_dev(dev);
2708 } 2731 }