Add basic hardware configure flow and device information statement.

Signed-off-by: Zaiyu Wang <zaiyuw...@trustnetic.com>
---
 doc/guides/nics/features/ngbe_vf.ini |   7 +
 drivers/net/ngbe/base/ngbe_mbx.h     |   2 +
 drivers/net/ngbe/base/ngbe_type.h    |   5 +
 drivers/net/ngbe/base/ngbe_vf.c      | 235 +++++++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_vf.h      |   9 +
 drivers/net/ngbe/ngbe_ethdev_vf.c    | 114 +++++++++++++
 6 files changed, 372 insertions(+)

diff --git a/doc/guides/nics/features/ngbe_vf.ini 
b/doc/guides/nics/features/ngbe_vf.ini
index 4da36e0085..53824a7c90 100644
--- a/doc/guides/nics/features/ngbe_vf.ini
+++ b/doc/guides/nics/features/ngbe_vf.ini
@@ -4,6 +4,13 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+CRC offload          = P
+VLAN offload         = P
+QinQ offload         = P
+L3 checksum offload  = P
+L4 checksum offload  = P
+Inner L3 checksum    = P
+Inner L4 checksum    = P
 Multiprocess aware   = Y
 Linux                = Y
 ARMv8                = Y
diff --git a/drivers/net/ngbe/base/ngbe_mbx.h b/drivers/net/ngbe/base/ngbe_mbx.h
index 83561fd4cf..27e977737d 100644
--- a/drivers/net/ngbe/base/ngbe_mbx.h
+++ b/drivers/net/ngbe/base/ngbe_mbx.h
@@ -57,6 +57,8 @@ enum ngbe_pfvf_api_rev {
 #define NGBE_VF_GET_RSS_KEY    0x0b    /* get RSS key */
 #define NGBE_VF_UPDATE_XCAST_MODE      0x0c
 
+#define NGBE_VF_BACKUP         0x8001 /* VF requests backup */
+
 /* mode choices for NGBE_VF_UPDATE_XCAST_MODE */
 enum ngbevf_xcast_modes {
        NGBEVF_XCAST_MODE_NONE = 0,
diff --git a/drivers/net/ngbe/base/ngbe_type.h 
b/drivers/net/ngbe/base/ngbe_type.h
index 35ebb7208a..4fd7080847 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -8,6 +8,9 @@
 
 #define NGBE_LINK_UP_TIME      90 /* 9.0 Seconds */
 
+#define NGBE_RX_HDR_SIZE       256
+#define NGBE_RX_BUF_SIZE       2048
+
 #define NGBE_FRAME_SIZE_MAX       (9728) /* Maximum frame size, +FCS */
 #define NGBE_FRAME_SIZE_DFT       (1518) /* Default frame size, +FCS */
 #define NGBE_NUM_POOL             (32)
@@ -17,6 +20,7 @@
 #define NGBE_MAX_QP               (8)
 #define NGBE_MAX_UTA              128
 
+#define NGBE_VF_INIT_TIMEOUT   200 /* Number of retries to clear RSTI */
 #define NGBE_PCI_MASTER_DISABLE_TIMEOUT        800
 #define NGBE_SPI_TIMEOUT       10000
 
@@ -480,6 +484,7 @@ struct ngbe_hw {
        u32 q_tx_regs[8 * 4];
        u32 gphy_efuse[2];
        bool offset_loaded;
+       bool rx_loaded;
        bool is_pf;
        bool gpio_ctl;
        bool lsc;
diff --git a/drivers/net/ngbe/base/ngbe_vf.c b/drivers/net/ngbe/base/ngbe_vf.c
index 12aa3bca1a..7c8b082f97 100644
--- a/drivers/net/ngbe/base/ngbe_vf.c
+++ b/drivers/net/ngbe/base/ngbe_vf.c
@@ -7,6 +7,178 @@
 #include "ngbe_mbx.h"
 #include "ngbe_vf.h"
 
+/* ngbe_virt_clr_reg - Set register to default (power on) state.
+ * @hw: pointer to hardware structure
+ */
+static void ngbe_virt_clr_reg(struct ngbe_hw *hw)
+{
+       u32 vfsrrctl;
+
+       /* default values (BUF_SIZE = 2048, HDR_SIZE = 256) */
+       vfsrrctl = NGBE_RXCFG_HDRLEN(NGBE_RX_HDR_SIZE);
+       vfsrrctl |= NGBE_RXCFG_PKTLEN(NGBE_RX_BUF_SIZE);
+
+       wr32m(hw, NGBE_RXCFG(0),
+               (NGBE_RXCFG_HDRLEN_MASK | NGBE_RXCFG_PKTLEN_MASK),
+               vfsrrctl);
+
+
+       ngbe_flush(hw);
+}
+
+/**
+ *  ngbe_start_hw_vf - Prepare hardware for Tx/Rx
+ *  @hw: pointer to hardware structure
+ *
+ *  Starts the hardware by filling the bus info structure and media type, 
clears
+ *  all on chip counters, initializes receive address registers, multicast
+ *  table, VLAN filter table, calls routine to set up link and flow control
+ *  settings, and leaves transmit and receive units disabled and uninitialized
+ **/
+s32 ngbe_start_hw_vf(struct ngbe_hw *hw)
+{
+       /* Clear adapter stopped flag */
+       hw->adapter_stopped = false;
+
+       return 0;
+}
+
+/**
+ *  ngbe_init_hw_vf - virtual function hardware initialization
+ *  @hw: pointer to hardware structure
+ *
+ *  Initialize the hardware by resetting the hardware and then starting
+ *  the hardware
+ **/
+s32 ngbe_init_hw_vf(struct ngbe_hw *hw)
+{
+       s32 status = hw->mac.start_hw(hw);
+
+       hw->mac.get_mac_addr(hw, hw->mac.addr);
+
+       return status;
+}
+
+/**
+ *  ngbe_reset_hw_vf - Performs hardware reset
+ *  @hw: pointer to hardware structure
+ *
+ *  Resets the hardware by resetting the transmit and receive units, masks and
+ *  clears all interrupts.
+ **/
+s32 ngbe_reset_hw_vf(struct ngbe_hw *hw)
+{
+       struct ngbe_mbx_info *mbx = &hw->mbx;
+       u32 timeout = NGBE_VF_INIT_TIMEOUT;
+       s32 ret_val = NGBE_ERR_INVALID_MAC_ADDR;
+       u32 msgbuf[NGBE_VF_PERMADDR_MSG_LEN];
+       u8 *addr = (u8 *)(&msgbuf[1]);
+
+       /* Call adapter stop to disable tx/rx and clear interrupts */
+       hw->mac.stop_hw(hw);
+
+       /* reset the api version */
+       hw->api_version = ngbe_mbox_api_10;
+
+       /* backup msix vectors */
+       mbx->timeout = NGBE_VF_MBX_INIT_TIMEOUT;
+       msgbuf[0] = NGBE_VF_BACKUP;
+       mbx->write_posted(hw, msgbuf, 1, 0);
+       msec_delay(10);
+
+       DEBUGOUT("Issuing a function level reset to MAC");
+       wr32(hw, NGBE_VFRST, NGBE_VFRST_SET);
+       ngbe_flush(hw);
+       msec_delay(50);
+
+       hw->offset_loaded = 1;
+
+       /* we cannot reset while the RSTI / RSTD bits are asserted */
+       while (!mbx->check_for_rst(hw, 0) && timeout) {
+               timeout--;
+               usec_delay(5);
+       }
+
+       if (!timeout)
+               return NGBE_ERR_RESET_FAILED;
+
+       /* Reset VF registers to initial values */
+       ngbe_virt_clr_reg(hw);
+
+       /* mailbox timeout can now become active */
+       mbx->timeout = NGBE_VF_MBX_INIT_TIMEOUT;
+
+       msgbuf[0] = NGBE_VF_RESET;
+       mbx->write_posted(hw, msgbuf, 1, 0);
+
+       msec_delay(10);
+
+       /*
+        * set our "perm_addr" based on info provided by PF
+        * also set up the mc_filter_type which is piggy backed
+        * on the mac address in word 3
+        */
+       ret_val = mbx->read_posted(hw, msgbuf,
+                       NGBE_VF_PERMADDR_MSG_LEN, 0);
+       if (ret_val)
+               return ret_val;
+
+       if (msgbuf[0] != (NGBE_VF_RESET | NGBE_VT_MSGTYPE_ACK) &&
+           msgbuf[0] != (NGBE_VF_RESET | NGBE_VT_MSGTYPE_NACK))
+               return NGBE_ERR_INVALID_MAC_ADDR;
+
+       if (msgbuf[0] == (NGBE_VF_RESET | NGBE_VT_MSGTYPE_ACK))
+               memcpy(hw->mac.perm_addr, addr, ETH_ADDR_LEN);
+
+       hw->mac.mc_filter_type = msgbuf[NGBE_VF_MC_TYPE_WORD];
+
+       return ret_val;
+}
+
+/**
+ *  ngbe_stop_hw_vf - Generic stop Tx/Rx units
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets the adapter_stopped flag within ngbe_hw struct. Clears interrupts,
+ *  disables transmit and receive units. The adapter_stopped flag is used by
+ *  the shared code and drivers to determine if the adapter is in a stopped
+ *  state and should not touch the hardware.
+ **/
+s32 ngbe_stop_hw_vf(struct ngbe_hw *hw)
+{
+       u16 i;
+
+       /*
+        * Set the adapter_stopped flag so other driver functions stop touching
+        * the hardware
+        */
+       hw->adapter_stopped = true;
+
+       /* Clear interrupt mask to stop from interrupts being generated */
+       wr32(hw, NGBE_VFIMC, NGBE_VFIMC_MASK);
+
+       /* Clear any pending interrupts, flush previous writes */
+       wr32(hw, NGBE_VFICR, NGBE_VFICR_MASK);
+
+       /* Disable the transmit unit.  Each queue must be disabled. */
+       for (i = 0; i < hw->mac.max_tx_queues; i++)
+               wr32(hw, NGBE_TXCFG(i), NGBE_TXCFG_FLUSH);
+
+       /* Disable the receive unit by stopping each queue */
+       for (i = 0; i < hw->mac.max_rx_queues; i++)
+               wr32m(hw, NGBE_RXCFG(i), NGBE_RXCFG_ENA, 0);
+
+       /* Clear packet split and pool config */
+       wr32(hw, NGBE_VFPLCFG, 0);
+       hw->rx_loaded = 1;
+
+       /* flush all queues disables */
+       ngbe_flush(hw);
+       msec_delay(2);
+
+       return 0;
+}
+
 STATIC s32 ngbevf_write_msg_read_ack(struct ngbe_hw *hw, u32 *msg,
                                      u32 *retmsg, u16 size)
 {
@@ -50,6 +222,64 @@ int ngbevf_negotiate_api_version(struct ngbe_hw *hw, int 
api)
        return err;
 }
 
+int ngbevf_get_queues(struct ngbe_hw *hw, unsigned int *num_tcs,
+                      unsigned int *default_tc)
+{
+       int err, i;
+       u32 msg[5];
+
+       /* do nothing if API doesn't support ngbevf_get_queues */
+       switch (hw->api_version) {
+       case ngbe_mbox_api_11:
+       case ngbe_mbox_api_12:
+       case ngbe_mbox_api_13:
+               break;
+       default:
+               return 0;
+       }
+
+       /* Fetch queue configuration from the PF */
+       msg[0] = NGBE_VF_GET_QUEUES;
+       for (i = 1; i < 5; i++)
+               msg[i] = 0;
+
+       err = ngbevf_write_msg_read_ack(hw, msg, msg, 5);
+       if (!err) {
+               msg[0] &= ~NGBE_VT_MSGTYPE_CTS;
+
+               /*
+                * if we didn't get an ACK there must have been
+                * some sort of mailbox error so we should treat it
+                * as such
+                */
+               if (msg[0] != (NGBE_VF_GET_QUEUES | NGBE_VT_MSGTYPE_ACK))
+                       return NGBE_ERR_MBX;
+
+               /* record and validate values from message */
+               hw->mac.max_tx_queues = msg[NGBE_VF_TX_QUEUES];
+               if (hw->mac.max_tx_queues == 0 ||
+                   hw->mac.max_tx_queues > NGBE_VF_MAX_TX_QUEUES)
+                       hw->mac.max_tx_queues = NGBE_VF_MAX_TX_QUEUES;
+
+               hw->mac.max_rx_queues = msg[NGBE_VF_RX_QUEUES];
+               if (hw->mac.max_rx_queues == 0 ||
+                   hw->mac.max_rx_queues > NGBE_VF_MAX_RX_QUEUES)
+                       hw->mac.max_rx_queues = NGBE_VF_MAX_RX_QUEUES;
+
+               *num_tcs = msg[NGBE_VF_TRANS_VLAN];
+               /* in case of unknown state assume we cannot tag frames */
+               if (*num_tcs > hw->mac.max_rx_queues)
+                       *num_tcs = 1;
+
+               *default_tc = msg[NGBE_VF_DEF_QUEUE];
+               /* default to queue 0 on out-of-bounds queue number */
+               if (*default_tc >= hw->mac.max_tx_queues)
+                       *default_tc = 0;
+       }
+
+       return err;
+}
+
 /**
  *  ngbe_init_ops_vf - Initialize the pointers for vf
  *  @hw: pointer to hardware structure
@@ -64,6 +294,11 @@ s32 ngbe_init_ops_vf(struct ngbe_hw *hw)
        struct ngbe_mac_info *mac = &hw->mac;
        struct ngbe_mbx_info *mbx = &hw->mbx;
 
+       /* MAC */
+       mac->init_hw = ngbe_init_hw_vf;
+       mac->reset_hw = ngbe_reset_hw_vf;
+       mac->start_hw = ngbe_start_hw_vf;
+       mac->stop_hw = ngbe_stop_hw_vf;
        mac->negotiate_api_version = ngbevf_negotiate_api_version;
 
        mac->max_tx_queues = 1;
diff --git a/drivers/net/ngbe/base/ngbe_vf.h b/drivers/net/ngbe/base/ngbe_vf.h
index 23e5b0d8a3..da846dda45 100644
--- a/drivers/net/ngbe/base/ngbe_vf.h
+++ b/drivers/net/ngbe/base/ngbe_vf.h
@@ -8,7 +8,16 @@
 
 #include "ngbe_type.h"
 
+#define NGBE_VF_MAX_TX_QUEUES  1
+#define NGBE_VF_MAX_RX_QUEUES  1
+
 s32 ngbe_init_ops_vf(struct ngbe_hw *hw);
+s32 ngbe_init_hw_vf(struct ngbe_hw *hw);
+s32 ngbe_start_hw_vf(struct ngbe_hw *hw);
+s32 ngbe_reset_hw_vf(struct ngbe_hw *hw);
+s32 ngbe_stop_hw_vf(struct ngbe_hw *hw);
 int ngbevf_negotiate_api_version(struct ngbe_hw *hw, int api);
+int ngbevf_get_queues(struct ngbe_hw *hw, unsigned int *num_tcs,
+                      unsigned int *default_tc);
 
 #endif /* __NGBE_VF_H__ */
diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c 
b/drivers/net/ngbe/ngbe_ethdev_vf.c
index 164a97fac1..ed8400f6ed 100644
--- a/drivers/net/ngbe/ngbe_ethdev_vf.c
+++ b/drivers/net/ngbe/ngbe_ethdev_vf.c
@@ -38,8 +38,48 @@ static const struct rte_pci_id pci_id_ngbevf_map[] = {
        { .vendor_id = 0, /* sentinel */ },
 };
 
+static const struct rte_eth_desc_lim rx_desc_lim = {
+       .nb_max = NGBE_RING_DESC_MAX,
+       .nb_min = NGBE_RING_DESC_MIN,
+       .nb_align = NGBE_RXD_ALIGN,
+};
+
+static const struct rte_eth_desc_lim tx_desc_lim = {
+       .nb_max = NGBE_RING_DESC_MAX,
+       .nb_min = NGBE_RING_DESC_MIN,
+       .nb_align = NGBE_TXD_ALIGN,
+       .nb_seg_max = NGBE_TX_MAX_SEG,
+       .nb_mtu_seg_max = NGBE_TX_MAX_SEG,
+};
+
 static const struct eth_dev_ops ngbevf_eth_dev_ops;
 
+/*
+ * Negotiate mailbox API version with the PF.
+ * After reset API version is always set to the basic one (ngbe_mbox_api_10).
+ * Then we try to negotiate starting with the most recent one.
+ * If all negotiation attempts fail, then we will proceed with
+ * the default one (ngbe_mbox_api_10).
+ */
+static void
+ngbevf_negotiate_api(struct ngbe_hw *hw)
+{
+       int32_t i;
+
+       /* start with highest supported, proceed down */
+       static const int sup_ver[] = {
+               ngbe_mbox_api_13,
+               ngbe_mbox_api_12,
+               ngbe_mbox_api_11,
+               ngbe_mbox_api_10,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(sup_ver); i++) {
+               if (ngbevf_negotiate_api_version(hw, sup_ver[i]) == 0)
+                       break;
+       }
+}
+
 /*
  * Virtual Function device init
  */
@@ -47,6 +87,7 @@ static int
 eth_ngbevf_dev_init(struct rte_eth_dev *eth_dev)
 {
        int err;
+       uint32_t tc, tcs;
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
 
@@ -70,7 +111,32 @@ eth_ngbevf_dev_init(struct rte_eth_dev *eth_dev)
                return -EIO;
        }
 
+       /* init_mailbox_params */
+       hw->mbx.init_params(hw);
+
        hw->mac.num_rar_entries = 32; /* The MAX of the underlying PF */
+       err = hw->mac.reset_hw(hw);
+
+       /*
+        * The VF reset operation returns the NGBE_ERR_INVALID_MAC_ADDR when
+        * the underlying PF driver has not assigned a MAC address to the VF.
+        * In this case, assign a random MAC address.
+        */
+       if (err != 0 && err != NGBE_ERR_INVALID_MAC_ADDR) {
+               PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", err);
+               /*
+                * This error code will be propagated to the app by
+                * rte_eth_dev_reset, so use a public error code rather than
+                * the internal-only NGBE_ERR_RESET_FAILED
+                */
+               return -EAGAIN;
+       }
+
+       /* negotiate mailbox API version to use with the PF. */
+       ngbevf_negotiate_api(hw);
+
+       /* Get Rx/Tx queue count via mailbox, which is ready after reset_hw */
+       ngbevf_get_queues(hw, &tcs, &tc);
 
        /* Allocate memory for storing MAC addresses */
        eth_dev->data->mac_addrs = rte_zmalloc("ngbevf", RTE_ETHER_ADDR_LEN *
@@ -82,6 +148,13 @@ eth_ngbevf_dev_init(struct rte_eth_dev *eth_dev)
                return -ENOMEM;
        }
 
+       /* reset the hardware with the new settings */
+       err = hw->mac.start_hw(hw);
+       if (err) {
+               PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", err);
+               return -EIO;
+       }
+
        PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
                     pci_dev->id.device_id, "ngbe_mac_sp_vf");
@@ -129,10 +202,47 @@ static int
 ngbevf_dev_info_get(struct rte_eth_dev *dev,
                     struct rte_eth_dev_info *dev_info)
 {
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct ngbe_hw *hw = ngbe_dev_hw(dev);
 
        dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues;
        dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues;
+       dev_info->min_rx_bufsize = 1024;
+       dev_info->max_rx_pktlen = NGBE_FRAME_SIZE_MAX;
+       dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+       dev_info->max_hash_mac_addrs = NGBE_VMDQ_NUM_UC_MAC;
+       dev_info->max_vfs = pci_dev->max_vfs;
+       dev_info->max_vmdq_pools = RTE_ETH_64_POOLS;
+       dev_info->rx_queue_offload_capa = ngbe_get_rx_queue_offloads(dev);
+       dev_info->rx_offload_capa = (ngbe_get_rx_port_offloads(dev) |
+                                    dev_info->rx_queue_offload_capa);
+       dev_info->tx_queue_offload_capa = 0;
+       dev_info->tx_offload_capa = ngbe_get_tx_port_offloads(dev);
+       dev_info->hash_key_size = NGBE_HKEY_MAX_INDEX * sizeof(uint32_t);
+       dev_info->reta_size = RTE_ETH_RSS_RETA_SIZE_128;
+       dev_info->default_rxconf = (struct rte_eth_rxconf) {
+               .rx_thresh = {
+                       .pthresh = NGBE_DEFAULT_RX_PTHRESH,
+                       .hthresh = NGBE_DEFAULT_RX_HTHRESH,
+                       .wthresh = NGBE_DEFAULT_RX_WTHRESH,
+               },
+               .rx_free_thresh = NGBE_DEFAULT_RX_FREE_THRESH,
+               .rx_drop_en = 0,
+               .offloads = 0,
+       };
+
+       dev_info->default_txconf = (struct rte_eth_txconf) {
+               .tx_thresh = {
+                       .pthresh = NGBE_DEFAULT_TX_PTHRESH,
+                       .hthresh = NGBE_DEFAULT_TX_HTHRESH,
+                       .wthresh = NGBE_DEFAULT_TX_WTHRESH,
+               },
+               .tx_free_thresh = NGBE_DEFAULT_TX_FREE_THRESH,
+               .offloads = 0,
+       };
+
+       dev_info->rx_desc_lim = rx_desc_lim;
+       dev_info->tx_desc_lim = tx_desc_lim;
 
        return 0;
 }
@@ -140,10 +250,14 @@ ngbevf_dev_info_get(struct rte_eth_dev *dev,
 static int
 ngbevf_dev_close(struct rte_eth_dev *dev)
 {
+       struct ngbe_hw *hw = ngbe_dev_hw(dev);
+
        PMD_INIT_FUNC_TRACE();
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
+       hw->mac.reset_hw(hw);
+
        rte_free(dev->data->mac_addrs);
        dev->data->mac_addrs = NULL;
 
-- 
2.21.0.windows.1

Reply via email to