aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/skge.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2011-09-27 13:41:37 -0400
committerDavid S. Miller <davem@davemloft.net>2011-09-27 13:41:37 -0400
commita9e9fd7182332d0cf5f3e601df3e71dd431b70d7 (patch)
treeabb7efe0ebaf78b4026bfd3117b85a9b9ef4b119 /drivers/net/ethernet/marvell/skge.c
parent04b71175f340d4081680440e1b9cbffcd3f4a13c (diff)
skge: handle irq better on single port card
Most boards with SysKonnect/Marvell Ethernet have only a single port. For the single port case, use the standard Ethernet driver convention of allocating IRQ when device is brought up rather than at probe time. This patch also adds some additional read after writes to avoid any PCI posting problems when setting the IRQ mask. The error handling of dual port cards is also changed. If second port can not be brought up, then just fail. No point in continuing, since the failure is most certainly because of out of memory. It is worth noting that the dual port skge device has a single irq but two seperate status rings and therefore has two NAPI objects, one for each port. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/marvell/skge.c')
-rw-r--r--drivers/net/ethernet/marvell/skge.c72
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);
113static void genesis_mac_init(struct skge_hw *hw, int port); 113static void genesis_mac_init(struct skge_hw *hw, int port);
114static void genesis_link_up(struct skge_port *skge); 114static void genesis_link_up(struct skge_port *skge);
115static void skge_set_multicast(struct net_device *dev); 115static void skge_set_multicast(struct net_device *dev);
116static irqreturn_t skge_intr(int irq, void *dev_id);
116 117
117/* Avoid conditionals by using array */ 118/* Avoid conditionals by using array */
118static const int txqaddr[] = { Q_XA1, Q_XA2 }; 119static 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
3981err_out_unregister_dev1:
3982 unregister_netdev(dev1);
3983err_out_free_dev1:
3984 free_netdev(dev1);
3958err_out_unregister: 3985err_out_unregister:
3959 unregister_netdev(dev); 3986 unregister_netdev(dev);
3960err_out_free_netdev: 3987err_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)