diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/marvell/skge.c | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 88e5856e06db..a0a647154245 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c | |||
@@ -113,6 +113,7 @@ static void yukon_init(struct skge_hw *hw, int port); | |||
113 | static void genesis_mac_init(struct skge_hw *hw, int port); | 113 | static void genesis_mac_init(struct skge_hw *hw, int port); |
114 | static void genesis_link_up(struct skge_port *skge); | 114 | static void genesis_link_up(struct skge_port *skge); |
115 | static void skge_set_multicast(struct net_device *dev); | 115 | static void skge_set_multicast(struct net_device *dev); |
116 | static irqreturn_t skge_intr(int irq, void *dev_id); | ||
116 | 117 | ||
117 | /* Avoid conditionals by using array */ | 118 | /* Avoid conditionals by using array */ |
118 | static const int txqaddr[] = { Q_XA1, Q_XA2 }; | 119 | static const int txqaddr[] = { Q_XA1, Q_XA2 }; |
@@ -2568,6 +2569,16 @@ static int skge_up(struct net_device *dev) | |||
2568 | if (err) | 2569 | if (err) |
2569 | goto free_rx_ring; | 2570 | goto free_rx_ring; |
2570 | 2571 | ||
2572 | if (hw->ports == 1) { | ||
2573 | err = request_irq(hw->pdev->irq, skge_intr, IRQF_SHARED, | ||
2574 | dev->name, hw); | ||
2575 | if (err) { | ||
2576 | netdev_err(dev, "Unable to allocate interrupt %d error: %d\n", | ||
2577 | hw->pdev->irq, err); | ||
2578 | goto free_tx_ring; | ||
2579 | } | ||
2580 | } | ||
2581 | |||
2571 | /* Initialize MAC */ | 2582 | /* Initialize MAC */ |
2572 | spin_lock_bh(&hw->phy_lock); | 2583 | spin_lock_bh(&hw->phy_lock); |
2573 | if (is_genesis(hw)) | 2584 | if (is_genesis(hw)) |
@@ -2595,11 +2606,14 @@ static int skge_up(struct net_device *dev) | |||
2595 | spin_lock_irq(&hw->hw_lock); | 2606 | spin_lock_irq(&hw->hw_lock); |
2596 | hw->intr_mask |= portmask[port]; | 2607 | hw->intr_mask |= portmask[port]; |
2597 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2608 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
2609 | skge_read32(hw, B0_IMSK); | ||
2598 | spin_unlock_irq(&hw->hw_lock); | 2610 | spin_unlock_irq(&hw->hw_lock); |
2599 | 2611 | ||
2600 | napi_enable(&skge->napi); | 2612 | napi_enable(&skge->napi); |
2601 | return 0; | 2613 | return 0; |
2602 | 2614 | ||
2615 | free_tx_ring: | ||
2616 | kfree(skge->tx_ring.start); | ||
2603 | free_rx_ring: | 2617 | free_rx_ring: |
2604 | skge_rx_clean(skge); | 2618 | skge_rx_clean(skge); |
2605 | kfree(skge->rx_ring.start); | 2619 | kfree(skge->rx_ring.start); |
@@ -2640,9 +2654,13 @@ static int skge_down(struct net_device *dev) | |||
2640 | 2654 | ||
2641 | spin_lock_irq(&hw->hw_lock); | 2655 | spin_lock_irq(&hw->hw_lock); |
2642 | hw->intr_mask &= ~portmask[port]; | 2656 | hw->intr_mask &= ~portmask[port]; |
2643 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2657 | skge_write32(hw, B0_IMSK, (hw->ports == 1) ? 0 : hw->intr_mask); |
2658 | skge_read32(hw, B0_IMSK); | ||
2644 | spin_unlock_irq(&hw->hw_lock); | 2659 | spin_unlock_irq(&hw->hw_lock); |
2645 | 2660 | ||
2661 | if (hw->ports == 1) | ||
2662 | free_irq(hw->pdev->irq, hw); | ||
2663 | |||
2646 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); | 2664 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); |
2647 | if (is_genesis(hw)) | 2665 | if (is_genesis(hw)) |
2648 | genesis_stop(skge); | 2666 | genesis_stop(skge); |
@@ -3603,7 +3621,8 @@ static int skge_reset(struct skge_hw *hw) | |||
3603 | skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100)); | 3621 | skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100)); |
3604 | skge_write32(hw, B2_IRQM_CTRL, TIM_START); | 3622 | skge_write32(hw, B2_IRQM_CTRL, TIM_START); |
3605 | 3623 | ||
3606 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 3624 | /* Leave irq disabled until first port is brought up. */ |
3625 | skge_write32(hw, B0_IMSK, 0); | ||
3607 | 3626 | ||
3608 | for (i = 0; i < hw->ports; i++) { | 3627 | for (i = 0; i < hw->ports; i++) { |
3609 | if (is_genesis(hw)) | 3628 | if (is_genesis(hw)) |
@@ -3930,31 +3949,39 @@ static int __devinit skge_probe(struct pci_dev *pdev, | |||
3930 | goto err_out_free_netdev; | 3949 | goto err_out_free_netdev; |
3931 | } | 3950 | } |
3932 | 3951 | ||
3933 | err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, hw->irq_name, hw); | ||
3934 | if (err) { | ||
3935 | dev_err(&pdev->dev, "%s: cannot assign irq %d\n", | ||
3936 | dev->name, pdev->irq); | ||
3937 | goto err_out_unregister; | ||
3938 | } | ||
3939 | skge_show_addr(dev); | 3952 | skge_show_addr(dev); |
3940 | 3953 | ||
3941 | if (hw->ports > 1) { | 3954 | if (hw->ports > 1) { |
3942 | dev1 = skge_devinit(hw, 1, using_dac); | 3955 | dev1 = skge_devinit(hw, 1, using_dac); |
3943 | if (dev1 && register_netdev(dev1) == 0) | 3956 | if (!dev1) { |
3944 | skge_show_addr(dev1); | 3957 | err = -ENOMEM; |
3945 | else { | 3958 | goto err_out_unregister; |
3946 | /* Failure to register second port need not be fatal */ | ||
3947 | dev_warn(&pdev->dev, "register of second port failed\n"); | ||
3948 | hw->dev[1] = NULL; | ||
3949 | hw->ports = 1; | ||
3950 | if (dev1) | ||
3951 | free_netdev(dev1); | ||
3952 | } | 3959 | } |
3960 | |||
3961 | err = register_netdev(dev1); | ||
3962 | if (err) { | ||
3963 | dev_err(&pdev->dev, "cannot register second net device\n"); | ||
3964 | goto err_out_free_dev1; | ||
3965 | } | ||
3966 | |||
3967 | err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, | ||
3968 | hw->irq_name, hw); | ||
3969 | if (err) { | ||
3970 | dev_err(&pdev->dev, "cannot assign irq %d\n", | ||
3971 | pdev->irq); | ||
3972 | goto err_out_unregister_dev1; | ||
3973 | } | ||
3974 | |||
3975 | skge_show_addr(dev1); | ||
3953 | } | 3976 | } |
3954 | pci_set_drvdata(pdev, hw); | 3977 | pci_set_drvdata(pdev, hw); |
3955 | 3978 | ||
3956 | return 0; | 3979 | return 0; |
3957 | 3980 | ||
3981 | err_out_unregister_dev1: | ||
3982 | unregister_netdev(dev1); | ||
3983 | err_out_free_dev1: | ||
3984 | free_netdev(dev1); | ||
3958 | err_out_unregister: | 3985 | err_out_unregister: |
3959 | unregister_netdev(dev); | 3986 | unregister_netdev(dev); |
3960 | err_out_free_netdev: | 3987 | err_out_free_netdev: |
@@ -3992,14 +4019,19 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
3992 | 4019 | ||
3993 | spin_lock_irq(&hw->hw_lock); | 4020 | spin_lock_irq(&hw->hw_lock); |
3994 | hw->intr_mask = 0; | 4021 | hw->intr_mask = 0; |
3995 | skge_write32(hw, B0_IMSK, 0); | 4022 | |
3996 | skge_read32(hw, B0_IMSK); | 4023 | if (hw->ports > 1) { |
4024 | skge_write32(hw, B0_IMSK, 0); | ||
4025 | skge_read32(hw, B0_IMSK); | ||
4026 | free_irq(pdev->irq, hw); | ||
4027 | } | ||
3997 | spin_unlock_irq(&hw->hw_lock); | 4028 | spin_unlock_irq(&hw->hw_lock); |
3998 | 4029 | ||
3999 | skge_write16(hw, B0_LED, LED_STAT_OFF); | 4030 | skge_write16(hw, B0_LED, LED_STAT_OFF); |
4000 | skge_write8(hw, B0_CTST, CS_RST_SET); | 4031 | skge_write8(hw, B0_CTST, CS_RST_SET); |
4001 | 4032 | ||
4002 | free_irq(pdev->irq, hw); | 4033 | if (hw->ports > 1) |
4034 | free_irq(pdev->irq, hw); | ||
4003 | pci_release_regions(pdev); | 4035 | pci_release_regions(pdev); |
4004 | pci_disable_device(pdev); | 4036 | pci_disable_device(pdev); |
4005 | if (dev1) | 4037 | if (dev1) |