cxgb4vf: add call to Firmware to reset VF State.
[linux-2.6.git] / drivers / net / cxgb4vf / cxgb4vf_main.c
index d065516..c3449bb 100644 (file)
@@ -533,10 +533,9 @@ static int setup_sge_queues(struct adapter *adapter)
                struct port_info *pi = netdev_priv(dev);
                struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset];
                struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset];
-               int nqsets = (adapter->flags & USING_MSIX) ? pi->nqsets : 1;
                int qs;
 
-               for (qs = 0; qs < nqsets; qs++, rxq++, txq++) {
+               for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
                        err = t4vf_sge_alloc_rxq(adapter, &rxq->rspq, false,
                                                 dev, msix++,
                                                 &rxq->fl, t4vf_ethrx_handler);
@@ -565,10 +564,9 @@ static int setup_sge_queues(struct adapter *adapter)
                struct port_info *pi = netdev_priv(dev);
                struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset];
                struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset];
-               int nqsets = (adapter->flags & USING_MSIX) ? pi->nqsets : 1;
                int qs;
 
-               for (qs = 0; qs < nqsets; qs++, rxq++, txq++) {
+               for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
                        IQ_MAP(s, rxq->rspq.abs_id) = &rxq->rspq;
                        EQ_MAP(s, txq->q.abs_id) = &txq->q;
 
@@ -750,9 +748,14 @@ static int cxgb4vf_open(struct net_device *dev)
        /*
         * Note that this interface is up and start everything up ...
         */
-       dev->real_num_tx_queues = pi->nqsets;
+       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);
-       link_start(dev);
+       err = link_start(dev);
+       if (err)
+               return err;
        netif_tx_start_all_queues(dev);
        return 0;
 }
@@ -1102,18 +1105,6 @@ static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr)
        return 0;
 }
 
-/*
- * Return a TX Queue on which to send the specified skb.
- */
-static u16 cxgb4vf_select_queue(struct net_device *dev, struct sk_buff *skb)
-{
-       /*
-        * XXX For now just use the default hash but we probably want to
-        * XXX look at other possibilities ...
-        */
-       return skb_tx_hash(dev, skb);
-}
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /*
  * Poll all of our receive queues.  This is called outside of normal interrupt
@@ -2074,6 +2065,22 @@ static int adap_init0(struct adapter *adapter)
        }
 
        /*
+        * Some environments do not properly handle PCIE FLRs -- e.g. in Linux
+        * 2.6.31 and later we can't call pci_reset_function() in order to
+        * issue an FLR because of a self- deadlock on the device semaphore.
+        * Meanwhile, the OS infrastructure doesn't issue FLRs in all the
+        * cases where they're needed -- for instance, some versions of KVM
+        * fail to reset "Assigned Devices" when the VM reboots.  Therefore we
+        * use the firmware based reset in order to reset any per function
+        * state.
+        */
+       err = t4vf_fw_reset(adapter);
+       if (err < 0) {
+               dev_err(adapter->pdev_dev, "FW reset failed: err=%d\n", err);
+               return err;
+       }
+
+       /*
         * Grab basic operational parameters.  These will predominantly have
         * been set up by the Physical Function Driver or will be hard coded
         * into the adapter.  We just have to live with them ...  Note that
@@ -2416,7 +2423,6 @@ static const struct net_device_ops cxgb4vf_netdev_ops     = {
        .ndo_get_stats          = cxgb4vf_get_stats,
        .ndo_set_rx_mode        = cxgb4vf_set_rxmode,
        .ndo_set_mac_address    = cxgb4vf_set_mac_addr,
-       .ndo_select_queue       = cxgb4vf_select_queue,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = cxgb4vf_do_ioctl,
        .ndo_change_mtu         = cxgb4vf_change_mtu,
@@ -2464,23 +2470,24 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                version_printed = 1;
        }
 
+
        /*
-        * Reserve PCI resources for the device.  If we can't get them some
-        * other driver may have already claimed the device ...
+        * Initialize generic PCI device state.
         */
-       err = pci_request_regions(pdev, KBUILD_MODNAME);
+       err = pci_enable_device(pdev);
        if (err) {
-               dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+               dev_err(&pdev->dev, "cannot enable PCI device\n");
                return err;
        }
 
        /*
-        * Initialize generic PCI device state.
+        * Reserve PCI resources for the device.  If we can't get them some
+        * other driver may have already claimed the device ...
         */
-       err = pci_enable_device(pdev);
+       err = pci_request_regions(pdev, KBUILD_MODNAME);
        if (err) {
-               dev_err(&pdev->dev, "cannot enable PCI device\n");
-               goto err_release_regions;
+               dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+               goto err_disable_device;
        }
 
        /*
@@ -2493,14 +2500,14 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                if (err) {
                        dev_err(&pdev->dev, "unable to obtain 64-bit DMA for"
                                " coherent allocations\n");
-                       goto err_disable_device;
+                       goto err_release_regions;
                }
                pci_using_dac = 1;
        } else {
                err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                if (err != 0) {
                        dev_err(&pdev->dev, "no usable DMA configuration\n");
-                       goto err_disable_device;
+                       goto err_release_regions;
                }
                pci_using_dac = 0;
        }
@@ -2516,7 +2523,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
        adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
        if (!adapter) {
                err = -ENOMEM;
-               goto err_disable_device;
+               goto err_release_regions;
        }
        pci_set_drvdata(pdev, adapter);
        adapter->pdev = pdev;
@@ -2598,7 +2605,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                pi->xact_addr_filt = -1;
                pi->rx_offload = RX_CSO;
                netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
                netdev->irq = pdev->irq;
 
                netdev->features = (NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
@@ -2623,7 +2629,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
                netdev->do_ioctl = cxgb4vf_do_ioctl;
                netdev->change_mtu = cxgb4vf_change_mtu;
                netdev->set_mac_address = cxgb4vf_set_mac_addr;
-               netdev->select_queue = cxgb4vf_select_queue;
 #ifdef CONFIG_NET_POLL_CONTROLLER
                netdev->poll_controller = cxgb4vf_poll_controller;
 #endif
@@ -2752,13 +2757,13 @@ err_free_adapter:
        kfree(adapter);
        pci_set_drvdata(pdev, NULL);
 
-err_disable_device:
-       pci_disable_device(pdev);
-       pci_clear_master(pdev);
-
 err_release_regions:
        pci_release_regions(pdev);
        pci_set_drvdata(pdev, NULL);
+       pci_clear_master(pdev);
+
+err_disable_device:
+       pci_disable_device(pdev);
 
 err_out:
        return err;
@@ -2842,6 +2847,14 @@ static struct pci_device_id cxgb4vf_pci_tbl[] = {
        CH_DEVICE(0x4800, 0),   /* T440-dbg */
        CH_DEVICE(0x4801, 0),   /* T420-cr */
        CH_DEVICE(0x4802, 0),   /* T422-cr */
+       CH_DEVICE(0x4803, 0),   /* T440-cr */
+       CH_DEVICE(0x4804, 0),   /* T420-bch */
+       CH_DEVICE(0x4805, 0),   /* T440-bch */
+       CH_DEVICE(0x4806, 0),   /* T460-ch */
+       CH_DEVICE(0x4807, 0),   /* T420-so */
+       CH_DEVICE(0x4808, 0),   /* T420-cx */
+       CH_DEVICE(0x4809, 0),   /* T420-bt */
+       CH_DEVICE(0x480a, 0),   /* T404-bt */
        { 0, }
 };