libertas: separate libertas' Kconfig in it's own file
[safe/jmp/linux-2.6] / drivers / net / sky2.c
index 1b79d33..2ab5c39 100644 (file)
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.24"
+#define DRV_VERSION            "1.25"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -65,8 +65,8 @@
 #define RX_DEF_PENDING         RX_MAX_PENDING
 
 /* This is the worst case number of transmit list elements for a single skb:
-   VLAN + TSO + CKSUM + Data + skb_frags * DMA */
-#define MAX_SKB_TX_LE  (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS)
+   VLAN:GSO + CKSUM + Data + skb_frags * DMA */
+#define MAX_SKB_TX_LE  (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1))
 #define TX_MIN_PENDING         (MAX_SKB_TX_LE+1)
 #define TX_MAX_PENDING         4096
 #define TX_DEF_PENDING         127
@@ -256,6 +256,9 @@ static void sky2_power_on(struct sky2_hw *hw)
 
                sky2_read32(hw, B2_GP_IO);
        }
+
+       /* Turn on "driver loaded" LED */
+       sky2_write16(hw, B0_CTST, Y2_LED_STAT_ON);
 }
 
 static void sky2_power_aux(struct sky2_hw *hw)
@@ -269,11 +272,15 @@ static void sky2_power_aux(struct sky2_hw *hw)
                            Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
                            Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
 
-       /* switch power to VAUX */
-       if (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL)
+       /* switch power to VAUX if supported and PME from D3cold */
+       if ( (sky2_read32(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+            pci_pme_capable(hw->pdev, PCI_D3cold))
                sky2_write8(hw, B0_POWER_CTRL,
                            (PC_VAUX_ENA | PC_VCC_ENA |
                             PC_VAUX_ON | PC_VCC_OFF));
+
+       /* turn off "driver loaded LED" */
+       sky2_write16(hw, B0_CTST, Y2_LED_STAT_OFF);
 }
 
 static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
@@ -758,7 +765,7 @@ static void sky2_wol_init(struct sky2_port *sky2)
        if (sky2->wol & WAKE_MAGIC)
                ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT;
        else
-               ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;;
+               ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;
 
        ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT;
        sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl);
@@ -1207,9 +1214,6 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        }
 
        case SIOCSMIIREG:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-
                spin_lock_bh(&sky2->phy_lock);
                err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f,
                                   data->val_in);
@@ -1399,6 +1403,61 @@ nomem:
        return -ENOMEM;
 }
 
+static int sky2_alloc_buffers(struct sky2_port *sky2)
+{
+       struct sky2_hw *hw = sky2->hw;
+
+       /* must be power of 2 */
+       sky2->tx_le = pci_alloc_consistent(hw->pdev,
+                                          sky2->tx_ring_size *
+                                          sizeof(struct sky2_tx_le),
+                                          &sky2->tx_le_map);
+       if (!sky2->tx_le)
+               goto nomem;
+
+       sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info),
+                               GFP_KERNEL);
+       if (!sky2->tx_ring)
+               goto nomem;
+
+       sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
+                                          &sky2->rx_le_map);
+       if (!sky2->rx_le)
+               goto nomem;
+       memset(sky2->rx_le, 0, RX_LE_BYTES);
+
+       sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
+                               GFP_KERNEL);
+       if (!sky2->rx_ring)
+               goto nomem;
+
+       return 0;
+nomem:
+       return -ENOMEM;
+}
+
+static void sky2_free_buffers(struct sky2_port *sky2)
+{
+       struct sky2_hw *hw = sky2->hw;
+
+       if (sky2->rx_le) {
+               pci_free_consistent(hw->pdev, RX_LE_BYTES,
+                                   sky2->rx_le, sky2->rx_le_map);
+               sky2->rx_le = NULL;
+       }
+       if (sky2->tx_le) {
+               pci_free_consistent(hw->pdev,
+                                   sky2->tx_ring_size * sizeof(struct sky2_tx_le),
+                                   sky2->tx_le, sky2->tx_le_map);
+               sky2->tx_le = NULL;
+       }
+       kfree(sky2->tx_ring);
+       kfree(sky2->rx_ring);
+
+       sky2->tx_ring = NULL;
+       sky2->rx_ring = NULL;
+}
+
 /* Bring up network interface. */
 static int sky2_up(struct net_device *dev)
 {
@@ -1406,7 +1465,7 @@ static int sky2_up(struct net_device *dev)
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
        u32 imask, ramsize;
-       int cap, err = -ENOMEM;
+       int cap, err;
        struct net_device *otherdev = hw->dev[sky2->port^1];
 
        /*
@@ -1425,32 +1484,12 @@ static int sky2_up(struct net_device *dev)
 
        netif_carrier_off(dev);
 
-       /* must be power of 2 */
-       sky2->tx_le = pci_alloc_consistent(hw->pdev,
-                                          sky2->tx_ring_size *
-                                          sizeof(struct sky2_tx_le),
-                                          &sky2->tx_le_map);
-       if (!sky2->tx_le)
-               goto err_out;
-
-       sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info),
-                               GFP_KERNEL);
-       if (!sky2->tx_ring)
+       err = sky2_alloc_buffers(sky2);
+       if (err)
                goto err_out;
 
        tx_init(sky2);
 
-       sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
-                                          &sky2->rx_le_map);
-       if (!sky2->rx_le)
-               goto err_out;
-       memset(sky2->rx_le, 0, RX_LE_BYTES);
-
-       sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
-                               GFP_KERNEL);
-       if (!sky2->rx_ring)
-               goto err_out;
-
        sky2_mac_init(hw, port);
 
        /* Register is number of 4K blocks on internal RAM buffer. */
@@ -1458,7 +1497,6 @@ static int sky2_up(struct net_device *dev)
        if (ramsize > 0) {
                u32 rxspace;
 
-               hw->flags |= SKY2_HW_RAM_BUFFER;
                pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
                if (ramsize < 16)
                        rxspace = ramsize / 2;
@@ -1507,22 +1545,7 @@ static int sky2_up(struct net_device *dev)
        return 0;
 
 err_out:
-       if (sky2->rx_le) {
-               pci_free_consistent(hw->pdev, RX_LE_BYTES,
-                                   sky2->rx_le, sky2->rx_le_map);
-               sky2->rx_le = NULL;
-       }
-       if (sky2->tx_le) {
-               pci_free_consistent(hw->pdev,
-                                   sky2->tx_ring_size * sizeof(struct sky2_tx_le),
-                                   sky2->tx_le, sky2->tx_le_map);
-               sky2->tx_le = NULL;
-       }
-       kfree(sky2->tx_ring);
-       kfree(sky2->rx_ring);
-
-       sky2->tx_ring = NULL;
-       sky2->rx_ring = NULL;
+       sky2_free_buffers(sky2);
        return err;
 }
 
@@ -1543,11 +1566,13 @@ static unsigned tx_le_req(const struct sk_buff *skb)
 {
        unsigned count;
 
-       count = sizeof(dma_addr_t) / sizeof(u32);
-       count += skb_shinfo(skb)->nr_frags * count;
+       count = (skb_shinfo(skb)->nr_frags + 1)
+               * (sizeof(dma_addr_t) / sizeof(u32));
 
        if (skb_is_gso(skb))
                ++count;
+       else if (sizeof(dma_addr_t) == sizeof(u32))
+               ++count;        /* possible vlan */
 
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                ++count;
@@ -1574,7 +1599,8 @@ static void sky2_tx_unmap(struct pci_dev *pdev,
  * the number of ring elements will probably be less than the number
  * of list elements used.
  */
-static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
+                                  struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
@@ -1866,9 +1892,6 @@ static int sky2_down(struct net_device *dev)
        sky2_phy_power_down(hw, port);
        spin_unlock_bh(&sky2->phy_lock);
 
-       /* turn off LED's */
-       sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
-
        sky2_tx_reset(hw, port);
 
        /* Free any pending frames stuck in HW queue */
@@ -1876,20 +1899,7 @@ static int sky2_down(struct net_device *dev)
 
        sky2_rx_clean(sky2);
 
-       pci_free_consistent(hw->pdev, RX_LE_BYTES,
-                           sky2->rx_le, sky2->rx_le_map);
-       kfree(sky2->rx_ring);
-
-       pci_free_consistent(hw->pdev,
-                           sky2->tx_ring_size * sizeof(struct sky2_tx_le),
-                           sky2->tx_le, sky2->tx_le_map);
-       kfree(sky2->tx_ring);
-
-       sky2->tx_le = NULL;
-       sky2->rx_le = NULL;
-
-       sky2->rx_ring = NULL;
-       sky2->tx_ring = NULL;
+       sky2_free_buffers(sky2);
 
        return 0;
 }
@@ -2915,6 +2925,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
                        ++hw->ports;
        }
 
+       if (sky2_read8(hw, B2_E_0))
+               hw->flags |= SKY2_HW_RAM_BUFFER;
+
        return 0;
 }
 
@@ -2982,8 +2995,6 @@ static void sky2_reset(struct sky2_hw *hw)
        sky2_write8(hw, B2_TI_CTRL, TIM_STOP);
        sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
 
-       sky2_write8(hw, B0_Y2LED, LED_STAT_ON);
-
        /* Turn off descriptor polling */
        sky2_write32(hw, B28_DPT_CTRL, DPT_STOP);
 
@@ -4476,13 +4487,16 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0;
 
        err = -ENOMEM;
-       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+
+       hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:")
+                    + strlen(pci_name(pdev)) + 1, GFP_KERNEL);
        if (!hw) {
                dev_err(&pdev->dev, "cannot allocate hardware struct\n");
                goto err_out_free_regions;
        }
 
        hw->pdev = pdev;
+       sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev));
 
        hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
        if (!hw->regs) {
@@ -4528,7 +4542,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
 
        err = request_irq(pdev->irq, sky2_intr,
                          (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
-                         dev->name, hw);
+                         hw->irq_name, hw);
        if (err) {
                dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
                goto err_out_unregister;
@@ -4541,16 +4555,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        if (hw->ports > 1) {
                struct net_device *dev1;
 
+               err = -ENOMEM;
                dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default);
-               if (!dev1)
-                       dev_warn(&pdev->dev, "allocation for second device failed\n");
-               else if ((err = register_netdev(dev1))) {
+               if (dev1 && (err = register_netdev(dev1)) == 0)
+                       sky2_show_addr(dev1);
+               else {
                        dev_warn(&pdev->dev,
                                 "register of second port failed (%d)\n", err);
                        hw->dev[1] = NULL;
-                       free_netdev(dev1);
-               } else
-                       sky2_show_addr(dev1);
+                       hw->ports = 1;
+                       if (dev1)
+                               free_netdev(dev1);
+               }
        }
 
        setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw);
@@ -4600,7 +4616,6 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
 
        sky2_power_aux(hw);
 
-       sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
        sky2_write8(hw, B0_CTST, CS_RST_SET);
        sky2_read8(hw, B0_CTST);