diff options
author | Michael Chan <mchan@broadcom.com> | 2009-08-14 11:49:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-15 21:50:43 -0400 |
commit | a3059b12adae868c42629ecf058a94195ef1e958 (patch) | |
tree | d736fb5260aaf71d36d8b066b04db00135c4e605 /drivers/net/cnic.c | |
parent | 64c6460875957502541a4ba30835ac625a0bee79 (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/cnic.c')
-rw-r--r-- | drivers/net/cnic.c | 49 |
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 | ||
2396 | static int cnic_start_hw(struct cnic_dev *dev) | 2396 | static 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 | |||
2416 | static 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 | |||
2427 | static 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 | ||
2440 | err1: | 2464 | err1: |
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); |
2444 | err2: | ||
2445 | return err; | 2467 | return err; |
2446 | } | 2468 | } |
2447 | 2469 | ||
2448 | static void cnic_stop_bnx2_hw(struct cnic_dev *dev) | 2470 | static 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 | } |