diff options
| -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 | } |
