update Intel copyright years to 2014
[dpdk.git] / lib / librte_pmd_e1000 / igb_ethdev.c
index 4cea254..77244e6 100644 (file)
@@ -1,35 +1,34 @@
 /*-
  *   BSD LICENSE
  * 
- *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
  *   All rights reserved.
  * 
- *   Redistribution and use in source and binary forms, with or without 
- *   modification, are permitted provided that the following conditions 
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
  *   are met:
  * 
- *     * Redistributions of source code must retain the above copyright 
+ *     * Redistributions of source code must retain the above copyright
  *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright 
- *       notice, this list of conditions and the following disclaimer in 
- *       the documentation and/or other materials provided with the 
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
  *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its 
- *       contributors may be used to endorse or promote products derived 
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
  *       from this software without specific prior written permission.
  * 
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
  */
 
 #include <sys/queue.h>
@@ -184,6 +183,7 @@ static struct eth_dev_ops eth_igb_ops = {
        .rx_queue_setup       = eth_igb_rx_queue_setup,
        .rx_queue_release     = eth_igb_rx_queue_release,
        .rx_queue_count       = eth_igb_rx_queue_count,
+       .rx_descriptor_done   = eth_igb_rx_descriptor_done,
        .tx_queue_setup       = eth_igb_tx_queue_setup,
        .tx_queue_release     = eth_igb_tx_queue_release,
        .dev_led_on           = eth_igb_led_on,
@@ -471,6 +471,18 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
        PMD_INIT_LOG(DEBUG, "eth_igbvf_dev_init");
 
        eth_dev->dev_ops = &igbvf_eth_dev_ops;
+       eth_dev->rx_pkt_burst = &eth_igb_recv_pkts;
+       eth_dev->tx_pkt_burst = &eth_igb_xmit_pkts;
+
+       /* for secondary processes, we don't initialise any further as primary
+        * has already done this work. Only check we don't need a different
+        * RX function */
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY){
+               if (eth_dev->data->scattered_rx)
+                       eth_dev->rx_pkt_burst = &eth_igb_recv_scattered_pkts;
+               return 0;
+       }
+
        pci_dev = eth_dev->pci_dev;
 
        hw->device_id = pci_dev->id.device_id;
@@ -551,6 +563,17 @@ rte_igb_pmd_init(void)
        return 0;
 }
 
+static void
+igb_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev)
+{
+       struct e1000_hw *hw =
+               E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       /* RCTL: enable VLAN filter since VMDq always use VLAN filter */
+       uint32_t rctl = E1000_READ_REG(hw, E1000_RCTL);
+       rctl |= E1000_RCTL_VFE;
+       E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+}
+
 /*
  * VF Driver initialization routine.
  * Invoked one at EAL init time.
@@ -647,6 +670,11 @@ eth_igb_start(struct rte_eth_dev *dev)
                        ETH_VLAN_EXTEND_MASK;
        eth_igb_vlan_offload_set(dev, mask);
 
+       if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
+               /* Enable VLAN filter since VMDq always use VLAN filter */
+               igb_vmdq_vlan_hw_filter_enable(dev);
+       }
+               
        /*
         * Configure the Interrupt Moderation register (EITR) with the maximum
         * possible value (0xFFFF) to minimize "System Partial Write" issued by
@@ -726,8 +754,8 @@ eth_igb_start(struct rte_eth_dev *dev)
        if (dev->data->dev_conf.intr_conf.lsc != 0)
                ret = eth_igb_lsc_interrupt_setup(dev);
 
-        /* resume enabled intr since hw reset */
-        igb_intr_enable(dev);
+       /* resume enabled intr since hw reset */
+       igb_intr_enable(dev);
 
        PMD_INIT_LOG(DEBUG, "<<");
 
@@ -757,6 +785,15 @@ eth_igb_stop(struct rte_eth_dev *dev)
        igb_pf_reset_hw(hw);
        E1000_WRITE_REG(hw, E1000_WUC, 0);
 
+       /* Set bit for Go Link disconnect */
+       if (hw->mac.type >= e1000_82580) {
+               uint32_t phpm_reg;
+
+               phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+               phpm_reg |= E1000_82580_PM_GO_LINKD;
+               E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
+       }
+
        /* Power down the phy. Needed to make the link go Down */
        e1000_power_down_phy(hw);
 
@@ -778,6 +815,15 @@ eth_igb_close(struct rte_eth_dev *dev)
        igb_release_manageability(hw);
        igb_hw_control_release(hw);
 
+       /* Clear bit for Go Link disconnect */
+       if (hw->mac.type >= e1000_82580) {
+               uint32_t phpm_reg;
+
+               phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+               phpm_reg &= ~E1000_82580_PM_GO_LINKD;
+               E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
+       }
+
        igb_dev_clear_queues(dev);
 
        memset(&link, 0, sizeof(link));
@@ -1088,19 +1134,28 @@ eth_igb_infos_get(struct rte_eth_dev *dev,
        case e1000_82575:
                dev_info->max_rx_queues = 4;
                dev_info->max_tx_queues = 4;
+               dev_info->max_vmdq_pools = 0;
                break;
 
        case e1000_82576:
                dev_info->max_rx_queues = 16;
                dev_info->max_tx_queues = 16;
+               dev_info->max_vmdq_pools = ETH_8_POOLS;
                break;
 
        case e1000_82580:
                dev_info->max_rx_queues = 8;
                dev_info->max_tx_queues = 8;
+               dev_info->max_vmdq_pools = ETH_8_POOLS;
                break;
 
        case e1000_i350:
+               dev_info->max_rx_queues = 8;
+               dev_info->max_tx_queues = 8;
+               dev_info->max_vmdq_pools = ETH_8_POOLS;
+               break;
+
+       case e1000_i354:
                dev_info->max_rx_queues = 8;
                dev_info->max_tx_queues = 8;
                break;
@@ -1108,22 +1163,26 @@ eth_igb_infos_get(struct rte_eth_dev *dev,
        case e1000_i210:
                dev_info->max_rx_queues = 4;
                dev_info->max_tx_queues = 4;
+               dev_info->max_vmdq_pools = 0;
                break;
 
        case e1000_vfadapt:
                dev_info->max_rx_queues = 2;
                dev_info->max_tx_queues = 2;
+               dev_info->max_vmdq_pools = 0;
                break;
 
        case e1000_vfadapt_i350:
                dev_info->max_rx_queues = 1;
                dev_info->max_tx_queues = 1;
+               dev_info->max_vmdq_pools = 0;
                break;
 
        default:
                /* Should not happen */
                dev_info->max_rx_queues = 0;
                dev_info->max_tx_queues = 0;
+               dev_info->max_vmdq_pools = 0;
        }
 }
 
@@ -1668,6 +1727,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        };
        uint32_t rx_buf_size;
        uint32_t max_high_water;
+       uint32_t rctl;
 
        hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        rx_buf_size = igb_get_rx_buffer_size(hw);
@@ -1690,6 +1750,21 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 
        err = e1000_setup_link_generic(hw);
        if (err == E1000_SUCCESS) {
+
+               /* check if we want to forward MAC frames - driver doesn't have native
+                * capability to do that, so we'll write the registers ourselves */
+
+               rctl = E1000_READ_REG(hw, E1000_RCTL);
+
+               /* set or clear MFLCN.PMCF bit depending on configuration */
+               if (fc_conf->mac_ctrl_frame_fwd != 0)
+                       rctl |= E1000_RCTL_PMCF;
+               else
+                       rctl &= ~E1000_RCTL_PMCF;
+
+               E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+               E1000_WRITE_FLUSH(hw);
+
                return 0;
        }