]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/cxgb4vf/cxgb4vf_main.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / cxgb4vf / cxgb4vf_main.c
index 6bf464afa90ed1a60cf06bb91f31964cf82a7e5d..6aad64df4dcb84c01e9f777dfceee8fb58f2eab6 100644 (file)
@@ -280,9 +280,7 @@ static void name_msix_vecs(struct adapter *adapter)
                const struct port_info *pi = netdev_priv(dev);
                int qs, msi;
 
-               for (qs = 0, msi = MSIX_NIQFLINT;
-                    qs < pi->nqsets;
-                    qs++, msi++) {
+               for (qs = 0, msi = MSIX_IQFLINT; qs < pi->nqsets; qs++, msi++) {
                        snprintf(adapter->msix_info[msi].desc, namelen,
                                 "%s-%d", dev->name, qs);
                        adapter->msix_info[msi].desc[namelen] = 0;
@@ -309,7 +307,7 @@ static int request_msix_queue_irqs(struct adapter *adapter)
        /*
         * Ethernet queues.
         */
-       msi = MSIX_NIQFLINT;
+       msi = MSIX_IQFLINT;
        for_each_ethrxq(s, rxq) {
                err = request_irq(adapter->msix_info[msi].vec,
                                  t4vf_sge_intr_msix, 0,
@@ -337,7 +335,7 @@ static void free_msix_queue_irqs(struct adapter *adapter)
        int rxq, msi;
 
        free_irq(adapter->msix_info[MSIX_FW].vec, &s->fw_evtq);
-       msi = MSIX_NIQFLINT;
+       msi = MSIX_IQFLINT;
        for_each_ethrxq(s, rxq)
                free_irq(adapter->msix_info[msi++].vec,
                         &s->ethrxq[rxq].rspq);
@@ -527,7 +525,7 @@ static int setup_sge_queues(struct adapter *adapter)
         * brought up at which point lots of things get nailed down
         * permanently ...
         */
-       msix = MSIX_NIQFLINT;
+       msix = MSIX_IQFLINT;
        for_each_port(adapter, pidx) {
                struct net_device *dev = adapter->port[pidx];
                struct port_info *pi = netdev_priv(dev);
@@ -751,13 +749,19 @@ static int cxgb4vf_open(struct net_device *dev)
        netif_set_real_num_tx_queues(dev, pi->nqsets);
        err = netif_set_real_num_rx_queues(dev, pi->nqsets);
        if (err)
-               return err;
-       set_bit(pi->port_id, &adapter->open_device_map);
+               goto err_unwind;
        err = link_start(dev);
        if (err)
-               return err;
+               goto err_unwind;
+
        netif_tx_start_all_queues(dev);
+       set_bit(pi->port_id, &adapter->open_device_map);
        return 0;
+
+err_unwind:
+       if (adapter->open_device_map == 0)
+               adapter_down(adapter);
+       return err;
 }
 
 /*
@@ -766,13 +770,12 @@ static int cxgb4vf_open(struct net_device *dev)
  */
 static int cxgb4vf_stop(struct net_device *dev)
 {
-       int ret;
        struct port_info *pi = netdev_priv(dev);
        struct adapter *adapter = pi->adapter;
 
        netif_tx_stop_all_queues(dev);
        netif_carrier_off(dev);
-       ret = t4vf_enable_vi(adapter, pi->viid, false, false);
+       t4vf_enable_vi(adapter, pi->viid, false, false);
        pi->link_cfg.link_ok = 0;
 
        clear_bit(pi->port_id, &adapter->open_device_map);
@@ -1365,6 +1368,8 @@ struct queue_port_stats {
        u64 rx_csum;
        u64 vlan_ex;
        u64 vlan_ins;
+       u64 lro_pkts;
+       u64 lro_merged;
 };
 
 /*
@@ -1402,6 +1407,8 @@ static const char stats_strings[][ETH_GSTRING_LEN] = {
        "RxCsumGood        ",
        "VLANextractions   ",
        "VLANinsertions    ",
+       "GROPackets        ",
+       "GROMerged         ",
 };
 
 /*
@@ -1451,6 +1458,8 @@ static void collect_sge_port_stats(const struct adapter *adapter,
                stats->rx_csum += rxq->stats.rx_cso;
                stats->vlan_ex += rxq->stats.vlan_ex;
                stats->vlan_ins += txq->vlan_ins;
+               stats->lro_pkts += rxq->stats.lro_pkts;
+               stats->lro_merged += rxq->stats.lro_merged;
        }
 }
 
@@ -1546,15 +1555,20 @@ static void cxgb4vf_get_wol(struct net_device *dev,
        memset(&wol->sopass, 0, sizeof(wol->sopass));
 }
 
+/*
+ * TCP Segmentation Offload flags which we support.
+ */
+#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
+
 /*
  * Set TCP Segmentation Offloading feature capabilities.
  */
 static int cxgb4vf_set_tso(struct net_device *dev, u32 tso)
 {
        if (tso)
-               dev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+               dev->features |= TSO_FLAGS;
        else
-               dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+               dev->features &= ~TSO_FLAGS;
        return 0;
 }
 
@@ -2026,7 +2040,7 @@ static int __devinit setup_debugfs(struct adapter *adapter)
 {
        int i;
 
-       BUG_ON(adapter->debugfs_root == NULL);
+       BUG_ON(IS_ERR_OR_NULL(adapter->debugfs_root));
 
        /*
         * Debugfs support is best effort.
@@ -2045,9 +2059,9 @@ static int __devinit setup_debugfs(struct adapter *adapter)
  * Tear down the /sys/kernel/debug/cxgb4vf sub-nodes created above.  We leave
  * it to our caller to tear down the directory (debugfs_root).
  */
-static void __devexit cleanup_debugfs(struct adapter *adapter)
+static void cleanup_debugfs(struct adapter *adapter)
 {
-       BUG_ON(adapter->debugfs_root == NULL);
+       BUG_ON(IS_ERR_OR_NULL(adapter->debugfs_root));
 
        /*
         * Unlike our sister routine cleanup_proc(), we don't need to remove
@@ -2063,7 +2077,7 @@ static void __devexit cleanup_debugfs(struct adapter *adapter)
  * adapter parameters we're going to be using and initialize basic adapter
  * hardware support.
  */
-static int adap_init0(struct adapter *adapter)
+static int __devinit adap_init0(struct adapter *adapter)
 {
        struct vf_resources *vfres = &adapter->params.vfres;
        struct sge_params *sge_params = &adapter->params.sge;
@@ -2474,17 +2488,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
        struct port_info *pi;
        struct net_device *netdev;
 
-       /*
-        * Vet our module parameters.
-        */
-       if (msi != MSI_MSIX && msi != MSI_MSI) {
-               dev_err(&pdev->dev, "bad module parameter msi=%d; must be %d"
-                       " (MSI-X or MSI) or %d (MSI)\n", msi, MSI_MSIX,
-                       MSI_MSI);
-               err = -EINVAL;
-               goto err_out;
-       }
-
        /*
         * Print our driver banner the first time we're called to initialize a
         * device.
@@ -2494,7 +2497,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                version_printed = 1;
        }
 
-
        /*
         * Initialize generic PCI device state.
         */
@@ -2631,7 +2633,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                netif_carrier_off(netdev);
                netdev->irq = pdev->irq;
 
-               netdev->features = (NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
+               netdev->features = (NETIF_F_SG | TSO_FLAGS |
                                    NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                                    NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
                                    NETIF_F_GRO);
@@ -2698,11 +2700,11 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
        /*
         * Set up our debugfs entries.
         */
-       if (cxgb4vf_debugfs_root) {
+       if (!IS_ERR_OR_NULL(cxgb4vf_debugfs_root)) {
                adapter->debugfs_root =
                        debugfs_create_dir(pci_name(pdev),
                                           cxgb4vf_debugfs_root);
-               if (adapter->debugfs_root == NULL)
+               if (IS_ERR_OR_NULL(adapter->debugfs_root))
                        dev_warn(&pdev->dev, "could not create debugfs"
                                 " directory");
                else
@@ -2757,7 +2759,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
         */
 
 err_free_debugfs:
-       if (adapter->debugfs_root) {
+       if (!IS_ERR_OR_NULL(adapter->debugfs_root)) {
                cleanup_debugfs(adapter);
                debugfs_remove_recursive(adapter->debugfs_root);
        }
@@ -2789,7 +2791,6 @@ err_release_regions:
 err_disable_device:
        pci_disable_device(pdev);
 
-err_out:
        return err;
 }
 
@@ -2827,7 +2828,7 @@ static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
                /*
                 * Tear down our debugfs entries.
                 */
-               if (adapter->debugfs_root) {
+               if (!IS_ERR_OR_NULL(adapter->debugfs_root)) {
                        cleanup_debugfs(adapter);
                        debugfs_remove_recursive(adapter->debugfs_root);
                }
@@ -2860,6 +2861,46 @@ static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
        pci_release_regions(pdev);
 }
 
+/*
+ * "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt
+ * delivery.
+ */
+static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev)
+{
+       struct adapter *adapter;
+       int pidx;
+
+       adapter = pci_get_drvdata(pdev);
+       if (!adapter)
+               return;
+
+       /*
+        * Disable all Virtual Interfaces.  This will shut down the
+        * delivery of all ingress packets into the chip for these
+        * Virtual Interfaces.
+        */
+       for_each_port(adapter, pidx) {
+               struct net_device *netdev;
+               struct port_info *pi;
+
+               if (!test_bit(pidx, &adapter->registered_device_map))
+                       continue;
+
+               netdev = adapter->port[pidx];
+               if (!netdev)
+                       continue;
+
+               pi = netdev_priv(netdev);
+               t4vf_enable_vi(adapter, pi->viid, false, false);
+       }
+
+       /*
+        * Free up all Queues which will prevent further DMA and
+        * Interrupts allowing various internal pathways to drain.
+        */
+       t4vf_free_sge_resources(adapter);
+}
+
 /*
  * PCI Device registration data structures.
  */
@@ -2893,6 +2934,7 @@ static struct pci_driver cxgb4vf_driver = {
        .id_table       = cxgb4vf_pci_tbl,
        .probe          = cxgb4vf_pci_probe,
        .remove         = __devexit_p(cxgb4vf_pci_remove),
+       .shutdown       = __devexit_p(cxgb4vf_pci_shutdown),
 };
 
 /*
@@ -2902,14 +2944,25 @@ static int __init cxgb4vf_module_init(void)
 {
        int ret;
 
+       /*
+        * Vet our module parameters.
+        */
+       if (msi != MSI_MSIX && msi != MSI_MSI) {
+               printk(KERN_WARNING KBUILD_MODNAME
+                      ": bad module parameter msi=%d; must be %d"
+                      " (MSI-X or MSI) or %d (MSI)\n",
+                      msi, MSI_MSIX, MSI_MSI);
+               return -EINVAL;
+       }
+
        /* Debugfs support is optional, just warn if this fails */
        cxgb4vf_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-       if (!cxgb4vf_debugfs_root)
+       if (IS_ERR_OR_NULL(cxgb4vf_debugfs_root))
                printk(KERN_WARNING KBUILD_MODNAME ": could not create"
                       " debugfs entry, continuing\n");
 
        ret = pci_register_driver(&cxgb4vf_driver);
-       if (ret < 0)
+       if (ret < 0 && !IS_ERR_OR_NULL(cxgb4vf_debugfs_root))
                debugfs_remove(cxgb4vf_debugfs_root);
        return ret;
 }