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 f2c4a66..5319db9 100644 (file)
@@ -75,7 +75,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.4.4-1.401"
+#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;
@@ -255,6 +255,8 @@ struct myri10ge_priv {
        u32 read_write_dma;
        u32 link_changes;
        u32 msg_enable;
+       unsigned int board_number;
+       int rebooted;
 };
 
 static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
@@ -266,6 +268,13 @@ static char *myri10ge_fw_name = NULL;
 module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name");
 
+#define MYRI10GE_MAX_BOARDS 8
+static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] =
+    {[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL };
+module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL,
+                        0444);
+MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board");
+
 static int myri10ge_ecrc_enable = 1;
 module_param(myri10ge_ecrc_enable, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E");
@@ -319,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,
@@ -354,13 +359,16 @@ 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)
 {
        __raw_writel((__force __u32) val, (__force void __iomem *)p);
 }
 
+static struct net_device_stats *myri10ge_get_stats(struct net_device *dev);
+
 static int
 myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
                  struct myri10ge_cmd *data, int atomic)
@@ -1290,7 +1298,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
                remainder -= MYRI10GE_ALLOC_SIZE;
        }
 
-       if (mgp->csum_flag && myri10ge_lro) {
+       if (dev->features & NETIF_F_LRO) {
                rx_frags[0].page_offset += MXGEFW_PAD;
                rx_frags[0].size -= MXGEFW_PAD;
                len -= MXGEFW_PAD;
@@ -1412,6 +1420,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
 {
        struct myri10ge_rx_done *rx_done = &ss->rx_done;
        struct myri10ge_priv *mgp = ss->mgp;
+       struct net_device *netdev = mgp->dev;
        unsigned long rx_bytes = 0;
        unsigned long rx_packets = 0;
        unsigned long rx_ok;
@@ -1445,7 +1454,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
        ss->stats.rx_packets += rx_packets;
        ss->stats.rx_bytes += rx_bytes;
 
-       if (myri10ge_lro)
+       if (netdev->features & NETIF_F_LRO)
                lro_flush_all(&rx_done->lro_mgr);
 
        /* restock receive rings if needed */
@@ -1614,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;
 }
 
@@ -1686,7 +1706,7 @@ myri10ge_get_ringparam(struct net_device *netdev,
        ring->rx_mini_max_pending = mgp->ss[0].rx_small.mask + 1;
        ring->rx_max_pending = mgp->ss[0].rx_big.mask + 1;
        ring->rx_jumbo_max_pending = 0;
-       ring->tx_max_pending = mgp->ss[0].rx_small.mask + 1;
+       ring->tx_max_pending = mgp->ss[0].tx.mask + 1;
        ring->rx_mini_pending = ring->rx_mini_max_pending;
        ring->rx_pending = ring->rx_max_pending;
        ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
@@ -1706,12 +1726,17 @@ static u32 myri10ge_get_rx_csum(struct net_device *netdev)
 static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
 {
        struct myri10ge_priv *mgp = netdev_priv(netdev);
+       int err = 0;
 
        if (csum_enabled)
                mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
-       else
+       else {
+               u32 flags = ethtool_op_get_flags(netdev);
+               err = ethtool_op_set_flags(netdev, (flags & ~ETH_FLAG_LRO));
                mgp->csum_flag = 0;
-       return 0;
+
+       }
+       return err;
 }
 
 static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
@@ -1803,8 +1828,10 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
        int slice;
        int i;
 
+       /* 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;
@@ -1892,7 +1919,9 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
        .get_sset_count = myri10ge_get_sset_count,
        .get_ethtool_stats = myri10ge_get_ethtool_stats,
        .set_msglevel = myri10ge_set_msglevel,
-       .get_msglevel = myri10ge_get_msglevel
+       .get_msglevel = myri10ge_get_msglevel,
+       .get_flags = ethtool_op_get_flags,
+       .set_flags = ethtool_op_set_flags
 };
 
 static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
@@ -2536,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++)
@@ -2633,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;
@@ -2671,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 */
@@ -2732,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 */
@@ -2876,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
@@ -2921,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))
@@ -2953,22 +2988,23 @@ 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);
        memset(stats, 0, sizeof(*stats));
        for (i = 0; i < mgp->num_slices; i++) {
                slice_stats = &mgp->ss[i].stats;
@@ -2979,6 +3015,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
                stats->rx_dropped += slice_stats->rx_dropped;
                stats->tx_dropped += slice_stats->tx_dropped;
        }
+       spin_unlock(&mgp->stats_lock);
        return stats;
 }
 
@@ -3253,6 +3290,8 @@ abort:
 
 static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
 {
+       int overridden = 0;
+
        if (myri10ge_force_firmware == 0) {
                int link_width, exp_cap;
                u16 lnk;
@@ -3286,10 +3325,18 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
                }
        }
        if (myri10ge_fw_name != NULL) {
-               dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
-                        myri10ge_fw_name);
+               overridden = 1;
                mgp->fw_name = myri10ge_fw_name;
        }
+       if (mgp->board_number < MYRI10GE_MAX_BOARDS &&
+           myri10ge_fw_names[mgp->board_number] != NULL &&
+           strlen(myri10ge_fw_names[mgp->board_number])) {
+               mgp->fw_name = myri10ge_fw_names[mgp->board_number];
+               overridden = 1;
+       }
+       if (overridden)
+               dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
+                        mgp->fw_name);
 }
 
 #ifdef CONFIG_PM
@@ -3400,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
@@ -3417,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.
@@ -3467,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",
@@ -3489,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) {
 
@@ -3532,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;
 
@@ -3754,6 +3823,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        int status = -ENXIO;
        int dac_enabled;
        unsigned hdr_offset, ss_offset;
+       static int board_number;
 
        netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
        if (netdev == NULL) {
@@ -3770,6 +3840,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mgp->pause = myri10ge_flow_control;
        mgp->intr_coal_delay = myri10ge_intr_coal_delay;
        mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT);
+       mgp->board_number = board_number;
        init_waitqueue_head(&mgp->down_wq);
 
        if (pci_enable_device(pdev)) {
@@ -3884,6 +3955,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (dac_enabled)
                netdev->features |= NETIF_F_HIGHDMA;
+       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
@@ -3902,6 +3980,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
                    (unsigned long)mgp);
 
+       spin_lock_init(&mgp->stats_lock);
        SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
        INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
        status = register_netdev(netdev);
@@ -3919,6 +3998,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                         netdev->irq, mgp->tx_boundary, mgp->fw_name,
                         (mgp->wc_enabled ? "Enabled" : "Disabled"));
 
+       board_number++;
        return 0;
 
 abort_with_state:
@@ -4008,6 +4088,8 @@ static struct pci_device_id myri10ge_pci_tbl[] = {
        {0},
 };
 
+MODULE_DEVICE_TABLE(pci, myri10ge_pci_tbl);
+
 static struct pci_driver myri10ge_driver = {
        .name = "myri10ge",
        .probe = myri10ge_probe,