doc: whitespace changes in licenses
[dpdk.git] / lib / librte_pmd_e1000 / igb_ethdev.c
index c91881b..5a4ece0 100644 (file)
@@ -4,32 +4,31 @@
  *   Copyright(c) 2010-2013 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>
@@ -139,6 +138,8 @@ static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 #define IGB_LINK_UPDATE_CHECK_TIMEOUT  90  /* 9s */
 #define IGB_LINK_UPDATE_CHECK_INTERVAL 100 /* ms */
 
+#define IGBVF_PMD_NAME "rte_igbvf_pmd"     /* PMD name */
+
 static enum e1000_fc_mode igb_fc_setting = e1000_fc_full;
 
 /*
@@ -181,6 +182,8 @@ static struct eth_dev_ops eth_igb_ops = {
        .vlan_offload_set     = eth_igb_vlan_offload_set,
        .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,
@@ -283,6 +286,23 @@ igb_intr_disable(struct e1000_hw *hw)
        E1000_WRITE_FLUSH(hw);
 }
 
+static inline int32_t
+igb_pf_reset_hw(struct e1000_hw *hw)
+{
+       uint32_t ctrl_ext;
+       int32_t status;
+       status = e1000_reset_hw(hw);
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       /* Set PF Reset Done bit so PF/VF Mail Ops can work */
+       ctrl_ext |= E1000_CTRL_EXT_PFRSTD;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+       return status;
+}
 static void
 igb_identify_hardware(struct rte_eth_dev *dev)
 {
@@ -309,6 +329,7 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
                E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        struct e1000_vfta * shadow_vfta =
                        E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private);
+       uint32_t ctrl_ext;
 
        pci_dev = eth_dev->pci_dev;
        eth_dev->dev_ops = &eth_igb_ops;
@@ -349,7 +370,7 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
         * Start from a known state, this is important in reading the nvm
         * and mac from that.
         */
-       e1000_reset_hw(hw);
+       igb_pf_reset_hw(hw);
 
        /* Make sure we have a good EEPROM before we read from it */
        if (e1000_validate_nvm_checksum(hw) < 0) {
@@ -405,6 +426,15 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
                                        "SOL/IDER session");
        }
 
+       /* initialize PF if max_vfs not zero */
+       igb_pf_host_init(eth_dev);
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       /* Set PF Reset Done bit so PF/VF Mail Ops can work */
+       ctrl_ext |= E1000_CTRL_EXT_PFRSTD;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
        PMD_INIT_LOG(INFO, "port_id %d vendorID=0x%x deviceID=0x%x\n",
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
                     pci_dev->id.device_id);
@@ -460,7 +490,7 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
 
        /* Disable the interrupts for VF */
        igbvf_intr_disable(hw);
-
+       
        diag = hw->mac.ops.reset_hw(hw);
 
        /* Allocate memory for storing MAC addresses */
@@ -473,6 +503,7 @@ eth_igbvf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
                        ETHER_ADDR_LEN * hw->mac.rar_entry_count);
                return -ENOMEM;
        }
+       
        /* Copy the permanent MAC address */
        ether_addr_copy((struct ether_addr *) hw->mac.perm_addr,
                        &eth_dev->data->mac_addrs[0]);
@@ -555,6 +586,7 @@ eth_igb_start(struct rte_eth_dev *dev)
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        int ret, i, mask;
+       uint32_t ctrl_ext;
 
        PMD_INIT_LOG(DEBUG, ">>");
 
@@ -584,6 +616,15 @@ eth_igb_start(struct rte_eth_dev *dev)
 
        E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN);
 
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       /* Set PF Reset Done bit so PF/VF Mail Ops can work */
+       ctrl_ext |= E1000_CTRL_EXT_PFRSTD;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
+       /* configure PF module if SRIOV enabled */
+       igb_pf_host_configure(dev);
+
        /* Configure for OS presence */
        igb_init_manageability(hw);
 
@@ -713,9 +754,18 @@ eth_igb_stop(struct rte_eth_dev *dev)
        struct rte_eth_link link;
 
        igb_intr_disable(hw);
-       e1000_reset_hw(hw);
+       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);
 
@@ -737,6 +787,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));
@@ -805,7 +864,7 @@ igb_hardware_init(struct e1000_hw *hw)
                hw->fc.requested_mode = e1000_fc_none;
 
        /* Issue a global reset */
-       e1000_reset_hw(hw);
+       igb_pf_reset_hw(hw);
        E1000_WRITE_REG(hw, E1000_WUC, 0);
 
        diag = e1000_init_hw(hw);
@@ -1362,10 +1421,6 @@ igb_vlan_hw_strip_disable(struct rte_eth_dev *dev)
        reg = E1000_READ_REG(hw, E1000_CTRL);
        reg &= ~E1000_CTRL_VME;
        E1000_WRITE_REG(hw, E1000_CTRL, reg);
-
-       /* Update maximum frame size */
-       E1000_WRITE_REG(hw, E1000_RLPML,
-               dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE);
 }
 
 static void
@@ -1379,11 +1434,6 @@ igb_vlan_hw_strip_enable(struct rte_eth_dev *dev)
        reg = E1000_READ_REG(hw, E1000_CTRL);
        reg |= E1000_CTRL_VME;
        E1000_WRITE_REG(hw, E1000_CTRL, reg);
-
-       /* Update maximum frame size */
-       E1000_WRITE_REG(hw, E1000_RLPML,
-               dev->data->dev_conf.rxmode.max_rx_pkt_len);
-
 }
 
 static void
@@ -1398,6 +1448,11 @@ igb_vlan_hw_extend_disable(struct rte_eth_dev *dev)
        reg &= ~E1000_CTRL_EXT_EXTEND_VLAN;
        E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
 
+       /* Update maximum packet length */
+       if (dev->data->dev_conf.rxmode.jumbo_frame == 1)
+               E1000_WRITE_REG(hw, E1000_RLPML,
+                       dev->data->dev_conf.rxmode.max_rx_pkt_len +
+                                               VLAN_TAG_SIZE);
 }
 
 static void
@@ -1411,6 +1466,12 @@ igb_vlan_hw_extend_enable(struct rte_eth_dev *dev)
        reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
        reg |= E1000_CTRL_EXT_EXTEND_VLAN;
        E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+
+       /* Update maximum packet length */
+       if (dev->data->dev_conf.rxmode.jumbo_frame == 1)
+               E1000_WRITE_REG(hw, E1000_RLPML,
+                       dev->data->dev_conf.rxmode.max_rx_pkt_len +
+                                               2 * VLAN_TAG_SIZE);
 }
 
 static void
@@ -1490,6 +1551,9 @@ eth_igb_interrupt_get_status(struct rte_eth_dev *dev)
                intr->flags |= E1000_FLAG_NEED_LINK_UPDATE;
        }
 
+       if (icr & E1000_ICR_VMMB) 
+               intr->flags |= E1000_FLAG_MAILBOX;
+
        return 0;
 }
 
@@ -1514,6 +1578,10 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev)
        struct rte_eth_link link;
        int ret;
 
+       if (intr->flags & E1000_FLAG_MAILBOX) {
+               igb_pf_mbx_process(dev);
+               intr->flags &= ~E1000_FLAG_MAILBOX;
+       }
 
        igb_intr_enable(dev);
        rte_intr_enable(&(dev->pci_dev->intr_handle));
@@ -1647,13 +1715,18 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        return (-EIO);
 }
 
+#define E1000_RAH_POOLSEL_SHIFT      (18)
 static void
 eth_igb_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
                uint32_t index, __rte_unused uint32_t pool)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t rah;
 
        e1000_rar_set(hw, mac_addr->addr_bytes, index);
+       rah = E1000_READ_REG(hw, E1000_RAH(index));
+       rah |= (0x1 << (E1000_RAH_POOLSEL_SHIFT + pool));
+       E1000_WRITE_REG(hw, E1000_RAH(index), rah);
 }
 
 static void