Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / myri10ge / myri10ge.c
index d317011..5319db9 100644 (file)
@@ -75,7 +75,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.5.0-1.415"
+#define MYRI10GE_VERSION_STR "1.5.1-1.451"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -188,6 +188,7 @@ struct myri10ge_slice_state {
        dma_addr_t fw_stats_bus;
        int watchdog_tx_done;
        int watchdog_tx_req;
+       int watchdog_rx_done;
 #ifdef CONFIG_MYRI10GE_DCA
        int cached_dca_tag;
        int cpu;
@@ -206,7 +207,6 @@ struct myri10ge_priv {
        int big_bytes;
        int max_intr_slots;
        struct net_device *dev;
-       struct net_device_stats stats;
        spinlock_t stats_lock;
        u8 __iomem *sram;
        int sram_size;
@@ -256,6 +256,7 @@ struct myri10ge_priv {
        u32 link_changes;
        u32 msg_enable;
        unsigned int board_number;
+       int rebooted;
 };
 
 static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
@@ -327,10 +328,6 @@ static int myri10ge_debug = -1;    /* defaults above */
 module_param(myri10ge_debug, int, 0);
 MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
 
-static int myri10ge_lro = 1;
-module_param(myri10ge_lro, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload");
-
 static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;
 module_param(myri10ge_lro_max_pkts, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_lro_max_pkts,
@@ -362,7 +359,8 @@ MODULE_PARM_DESC(myri10ge_dca, "Enable DCA if possible");
 #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
 
 static void myri10ge_set_multicast_list(struct net_device *dev);
-static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+                                        struct net_device *dev);
 
 static inline void put_be32(__be32 val, __be32 __iomem * p)
 {
@@ -1625,10 +1623,21 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
                        return 0;
                }
        }
-       if (*ptr == 'R' || *ptr == 'Q') {
-               /* We've found either an XFP or quad ribbon fiber */
+       if (*ptr == '2')
+               ptr++;
+       if (*ptr == 'R' || *ptr == 'Q' || *ptr == 'S') {
+               /* We've found either an XFP, quad ribbon fiber, or SFP+ */
                cmd->port = PORT_FIBRE;
+               cmd->supported |= SUPPORTED_FIBRE;
+               cmd->advertising |= ADVERTISED_FIBRE;
+       } else {
+               cmd->port = PORT_OTHER;
        }
+       if (*ptr == 'R' || *ptr == 'S')
+               cmd->transceiver = XCVR_EXTERNAL;
+       else
+               cmd->transceiver = XCVR_INTERNAL;
+
        return 0;
 }
 
@@ -1822,7 +1831,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
        /* force stats update */
        (void)myri10ge_get_stats(netdev);
        for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
-               data[i] = ((unsigned long *)&mgp->stats)[i];
+               data[i] = ((unsigned long *)&netdev->stats)[i];
 
        data[i++] = (unsigned int)mgp->tx_boundary;
        data[i++] = (unsigned int)mgp->wc_enabled;
@@ -2556,17 +2565,22 @@ static int myri10ge_close(struct net_device *dev)
        netif_carrier_off(dev);
 
        netif_tx_stop_all_queues(dev);
-       old_down_cnt = mgp->down_cnt;
-       mb();
-       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
-       if (status)
-               printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
-                      dev->name);
-
-       wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
-       if (old_down_cnt == mgp->down_cnt)
-               printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+       if (mgp->rebooted == 0) {
+               old_down_cnt = mgp->down_cnt;
+               mb();
+               status =
+                   myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+               if (status)
+                       printk(KERN_ERR
+                              "myri10ge: %s: Couldn't bring down link\n",
+                              dev->name);
 
+               wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt,
+                                  HZ);
+               if (old_down_cnt == mgp->down_cnt)
+                       printk(KERN_ERR "myri10ge: %s never got down irq\n",
+                              dev->name);
+       }
        netif_tx_disable(dev);
        myri10ge_free_irq(mgp);
        for (i = 0; i < mgp->num_slices; i++)
@@ -2653,7 +2667,8 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
  * it and try again.
  */
 
-static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t myri10ge_xmit(struct sk_buff *skb,
+                                      struct net_device *dev)
 {
        struct myri10ge_priv *mgp = netdev_priv(dev);
        struct myri10ge_slice_state *ss;
@@ -2691,7 +2706,7 @@ again:
                /* we are out of transmit resources */
                tx->stop_queue++;
                netif_tx_stop_queue(netdev_queue);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        /* Setup checksum offloading, if needed */
@@ -2752,7 +2767,7 @@ again:
                                /* The packet is gone, so we must
                                 * return 0 */
                                ss->stats.tx_dropped += 1;
-                               return 0;
+                               return NETDEV_TX_OK;
                        }
                        /* adjust the len to account for the zero pad
                         * so that the nic can know how long it is */
@@ -2896,8 +2911,7 @@ again:
                tx->stop_queue++;
                netif_tx_stop_queue(netdev_queue);
        }
-       dev->trans_start = jiffies;
-       return 0;
+       return NETDEV_TX_OK;
 
 abort_linearize:
        /* Free any DMA resources we've alloced and clear out the skb
@@ -2941,16 +2955,17 @@ abort_linearize:
 drop:
        dev_kfree_skb_any(skb);
        ss->stats.tx_dropped += 1;
-       return 0;
+       return NETDEV_TX_OK;
 
 }
 
-static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+                                        struct net_device *dev)
 {
        struct sk_buff *segs, *curr;
        struct myri10ge_priv *mgp = netdev_priv(dev);
        struct myri10ge_slice_state *ss;
-       int status;
+       netdev_tx_t status;
 
        segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
        if (IS_ERR(segs))
@@ -2973,20 +2988,20 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
                }
        }
        dev_kfree_skb_any(skb);
-       return 0;
+       return NETDEV_TX_OK;
 
 drop:
        ss = &mgp->ss[skb_get_queue_mapping(skb)];
        dev_kfree_skb_any(skb);
        ss->stats.tx_dropped += 1;
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
 {
        struct myri10ge_priv *mgp = netdev_priv(dev);
        struct myri10ge_slice_netstats *slice_stats;
-       struct net_device_stats *stats = &mgp->stats;
+       struct net_device_stats *stats = &dev->stats;
        int i;
 
        spin_lock(&mgp->stats_lock);
@@ -3432,12 +3447,13 @@ static void myri10ge_watchdog(struct work_struct *work)
            container_of(work, struct myri10ge_priv, watchdog_work);
        struct myri10ge_tx_buf *tx;
        u32 reboot;
-       int status;
+       int status, rebooted;
        int i;
        u16 cmd, vendor;
 
        mgp->watchdog_resets++;
        pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+       rebooted = 0;
        if ((cmd & PCI_COMMAND_MASTER) == 0) {
                /* Bus master DMA disabled?  Check to see
                 * if the card rebooted due to a parity error
@@ -3449,9 +3465,12 @@ static void myri10ge_watchdog(struct work_struct *work)
                       myri10ge_reset_recover ? " " : " not");
                if (myri10ge_reset_recover == 0)
                        return;
-
+               rtnl_lock();
+               mgp->rebooted = 1;
+               rebooted = 1;
+               myri10ge_close(mgp->dev);
                myri10ge_reset_recover--;
-
+               mgp->rebooted = 0;
                /*
                 * A rebooted nic will come back with config space as
                 * it was after power was applied to PCIe bus.
@@ -3499,8 +3518,10 @@ static void myri10ge_watchdog(struct work_struct *work)
                }
        }
 
-       rtnl_lock();
-       myri10ge_close(mgp->dev);
+       if (!rebooted) {
+               rtnl_lock();
+               myri10ge_close(mgp->dev);
+       }
        status = myri10ge_load_firmware(mgp, 1);
        if (status != 0)
                printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
@@ -3521,12 +3542,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)
 {
        struct myri10ge_priv *mgp;
        struct myri10ge_slice_state *ss;
-       int i, reset_needed;
+       int i, reset_needed, busy_slice_cnt;
        u32 rx_pause_cnt;
+       u16 cmd;
 
        mgp = (struct myri10ge_priv *)arg;
 
        rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
+       busy_slice_cnt = 0;
        for (i = 0, reset_needed = 0;
             i < mgp->num_slices && reset_needed == 0; ++i) {
 
@@ -3564,8 +3587,22 @@ static void myri10ge_watchdog_timer(unsigned long arg)
                                reset_needed = 1;
                        }
                }
+               if (ss->watchdog_tx_done != ss->tx.done ||
+                   ss->watchdog_rx_done != ss->rx_done.cnt) {
+                       busy_slice_cnt++;
+               }
                ss->watchdog_tx_done = ss->tx.done;
                ss->watchdog_tx_req = ss->tx.req;
+               ss->watchdog_rx_done = ss->rx_done.cnt;
+       }
+       /* if we've sent or received no traffic, poll the NIC to
+        * ensure it is still there.  Otherwise, we risk not noticing
+        * an error in a timely fashion */
+       if (busy_slice_cnt == 0) {
+               pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+               if ((cmd & PCI_COMMAND_MASTER) == 0) {
+                       reset_needed = 1;
+               }
        }
        mgp->watchdog_pause = rx_pause_cnt;
 
@@ -3918,8 +3955,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (dac_enabled)
                netdev->features |= NETIF_F_HIGHDMA;
-       if (myri10ge_lro)
-               netdev->features |= NETIF_F_LRO;
+       netdev->features |= NETIF_F_LRO;
+
+       netdev->vlan_features |= mgp->features;
+       if (mgp->fw_ver_tiny < 37)
+               netdev->vlan_features &= ~NETIF_F_TSO6;
+       if (mgp->fw_ver_tiny < 32)
+               netdev->vlan_features &= ~NETIF_F_TSO;
 
        /* make sure we can get an irq, and that MSI can be
         * setup (if available).  Also ensure netdev->irq