For the design of the xsc PMD, each ethdev corresponds to a representor.

Signed-off-by: WanRenyong <wa...@yunsilicon.com>
---
 drivers/net/xsc/xsc_defs.h   |  11 +++
 drivers/net/xsc/xsc_dev.c    |  95 ++++++++++++++++++++
 drivers/net/xsc/xsc_dev.h    |   3 +
 drivers/net/xsc/xsc_ethdev.c | 170 +++++++++++++++++++++++++++++++++++
 drivers/net/xsc/xsc_ethdev.h |  19 ++++
 5 files changed, 298 insertions(+)

diff --git a/drivers/net/xsc/xsc_defs.h b/drivers/net/xsc/xsc_defs.h
index b1e37a5870..111776f37e 100644
--- a/drivers/net/xsc/xsc_defs.h
+++ b/drivers/net/xsc/xsc_defs.h
@@ -6,6 +6,7 @@
 #define XSC_DEFS_H_
 
 #define XSC_PAGE_SIZE                  4096
+#define XSC_PHY_PORT_NUM               1
 
 #define XSC_PCI_VENDOR_ID              0x1f67
 #define XSC_PCI_DEV_ID_MS              0x1111
@@ -15,6 +16,7 @@
 #define XSC_PCI_DEV_ID_MVS             0x1153
 
 #define XSC_VFREP_BASE_LOGICAL_PORT    1081
+#define XSC_MAX_MAC_ADDRESSES          3
 
 #define XSC_RSS_HASH_KEY_LEN           52
 #define XSC_RSS_HASH_BIT_IPV4_SIP      (1ULL << 0)
@@ -58,6 +60,15 @@ enum xsc_pph_type {
        XSC_UPLINK_PPH  = 0x8,
 };
 
+enum xsc_funcid_type {
+       XSC_FUNCID_TYPE_INVAL   = 0x0,
+       XSC_EMU_FUNCID          = 0x1,
+       XSC_PHYPORT_MAC_FUNCID  = 0x2,
+       XSC_VF_IOCTL_FUNCID     = 0x3,
+       XSC_PHYPORT_LAG_FUNCID  = 0x4,
+       XSC_FUNCID_TYPE_UNKNOWN = 0x5,
+};
+
 enum xsc_port_type {
        XSC_PORT_TYPE_NONE = 0,
        XSC_PORT_TYPE_UPLINK,
diff --git a/drivers/net/xsc/xsc_dev.c b/drivers/net/xsc/xsc_dev.c
index 8933f77b8f..aaf18bf8e5 100644
--- a/drivers/net/xsc/xsc_dev.c
+++ b/drivers/net/xsc/xsc_dev.c
@@ -61,6 +61,12 @@ xsc_dev_mailbox_exec(struct xsc_dev *xdev, void *data_in,
                                           data_out, out_len);
 }
 
+int
+xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac)
+{
+       return xdev->dev_ops->get_mac(xdev, mac);
+}
+
 int
 xsc_dev_close(struct xsc_dev *xdev, int repr_id)
 {
@@ -126,6 +132,95 @@ xsc_dev_args_parse(struct xsc_dev *xdev, struct 
rte_devargs *devargs)
        rte_kvargs_free(kvlist);
 }
 
+int
+xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id)
+{
+       if (xsc_dev_is_vf(xdev))
+               return 0;
+
+       return (repr_id % 511 + 1);
+}
+
+static void
+xsc_repr_info_init(struct xsc_dev *xdev, struct xsc_repr_info *info,
+                  enum xsc_port_type port_type,
+                  enum xsc_funcid_type funcid_type, int32_t repr_id)
+{
+       int qp_set_id, logical_port;
+       struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
+
+       info->repr_id = repr_id;
+       info->port_type = port_type;
+       if (port_type == XSC_PORT_TYPE_UPLINK_BOND) {
+               info->pf_bond = 1;
+               info->funcid = XSC_PHYPORT_LAG_FUNCID << 14;
+       } else if (port_type == XSC_PORT_TYPE_UPLINK) {
+               info->pf_bond = -1;
+               info->funcid = funcid_type << 14;
+       } else if (port_type == XSC_PORT_TYPE_PFVF) {
+               info->funcid = funcid_type << 14;
+       }
+
+       qp_set_id = xsc_dev_qp_set_id_get(xdev, repr_id);
+       if (xsc_dev_is_vf(xdev))
+               logical_port = xdev->hwinfo.func_id +
+                              xdev->hwinfo.funcid_to_logic_port_off;
+       else
+               logical_port = xdev->vfos_logical_in_port + qp_set_id - 1;
+
+       info->logical_port = logical_port;
+       info->local_dstinfo = logical_port;
+       info->peer_logical_port = hwinfo->mac_phy_port;
+       info->peer_dstinfo = hwinfo->mac_phy_port;
+}
+
+int
+xsc_dev_repr_ports_probe(struct xsc_dev *xdev, int nb_repr_ports, int 
max_eth_ports)
+{
+       int funcid_type;
+       struct xsc_repr_port *repr_port;
+       int i;
+
+       PMD_INIT_FUNC_TRACE();
+
+       xdev->num_repr_ports = nb_repr_ports + XSC_PHY_PORT_NUM;
+       if (xdev->num_repr_ports > max_eth_ports) {
+               PMD_DRV_LOG(ERR, "Repr ports num %u, should be less than max 
%u",
+                           xdev->num_repr_ports, max_eth_ports);
+               return -EINVAL;
+       }
+
+       xdev->repr_ports = rte_zmalloc(NULL,
+                                      sizeof(struct xsc_repr_port) * 
xdev->num_repr_ports,
+                                      RTE_CACHE_LINE_SIZE);
+       if (xdev->repr_ports == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to allocate memory for repr ports");
+               return -ENOMEM;
+       }
+
+       funcid_type = (xdev->devargs.nic_mode == XSC_NIC_MODE_SWITCHDEV) ?
+               XSC_VF_IOCTL_FUNCID : XSC_PHYPORT_MAC_FUNCID;
+
+       /* PF representor use the last repr_ports */
+       repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
+       xsc_repr_info_init(xdev, &repr_port->info, XSC_PORT_TYPE_UPLINK,
+                          XSC_PHYPORT_MAC_FUNCID, xdev->num_repr_ports - 1);
+       repr_port->info.ifindex = xdev->ifindex;
+       repr_port->xdev = xdev;
+       LIST_INIT(&repr_port->def_pct_list);
+
+       /* VF representor start from 0 */
+       for (i = 0; i < nb_repr_ports; i++) {
+               repr_port = &xdev->repr_ports[i];
+               xsc_repr_info_init(xdev, &repr_port->info,
+                                  XSC_PORT_TYPE_PFVF, funcid_type, i);
+               repr_port->xdev = xdev;
+               LIST_INIT(&repr_port->def_pct_list);
+       }
+
+       return 0;
+}
+
 void
 xsc_dev_uninit(struct xsc_dev *xdev)
 {
diff --git a/drivers/net/xsc/xsc_dev.h b/drivers/net/xsc/xsc_dev.h
index 54e0275411..297c5d2324 100644
--- a/drivers/net/xsc/xsc_dev.h
+++ b/drivers/net/xsc/xsc_dev.h
@@ -161,6 +161,9 @@ void xsc_dev_ops_register(struct xsc_dev_ops *new_ops);
 int xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **dev);
 void xsc_dev_uninit(struct xsc_dev *xdev);
 int xsc_dev_close(struct xsc_dev *xdev, int repr_id);
+int xsc_dev_repr_ports_probe(struct xsc_dev *xdev, int nb_repr_ports, int 
max_eth_ports);
 bool xsc_dev_is_vf(struct xsc_dev *xdev);
+int xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id);
+int xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac);
 
 #endif /* _XSC_DEV_H_ */
diff --git a/drivers/net/xsc/xsc_ethdev.c b/drivers/net/xsc/xsc_ethdev.c
index 4bdc70507f..9fc5464754 100644
--- a/drivers/net/xsc/xsc_ethdev.c
+++ b/drivers/net/xsc/xsc_ethdev.c
@@ -9,6 +9,166 @@
 #include "xsc_defs.h"
 #include "xsc_ethdev.h"
 
+static int
+xsc_ethdev_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 
uint32_t index)
+{
+       int i;
+
+       rte_errno = EINVAL;
+       if (index > XSC_MAX_MAC_ADDRESSES)
+               return -rte_errno;
+
+       if (rte_is_zero_ether_addr(mac))
+               return -rte_errno;
+
+       for (i = 0; i != XSC_MAX_MAC_ADDRESSES; ++i) {
+               if (i == (int)index)
+                       continue;
+               if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac)))
+                       continue;
+               /* Address already configured elsewhere, return with error */
+               rte_errno = EADDRINUSE;
+               return -rte_errno;
+       }
+
+       dev->data->mac_addrs[index] = *mac;
+       return 0;
+}
+
+static int
+xsc_ethdev_init_one_representor(struct rte_eth_dev *eth_dev, void *init_params)
+{
+       int ret;
+       struct xsc_repr_port *repr_port = (struct xsc_repr_port *)init_params;
+       struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
+       struct xsc_dev_config *config = &priv->config;
+       struct rte_ether_addr mac;
+
+       priv->repr_port = repr_port;
+       repr_port->drv_data = eth_dev;
+       priv->xdev = repr_port->xdev;
+       priv->mtu = RTE_ETHER_MTU;
+       priv->funcid_type = (repr_port->info.funcid & XSC_FUNCID_TYPE_MASK) >> 
14;
+       priv->funcid = repr_port->info.funcid & XSC_FUNCID_MASK;
+       if (repr_port->info.port_type == XSC_PORT_TYPE_UPLINK ||
+           repr_port->info.port_type == XSC_PORT_TYPE_UPLINK_BOND)
+               priv->eth_type = RTE_ETH_REPRESENTOR_PF;
+       else
+               priv->eth_type = RTE_ETH_REPRESENTOR_VF;
+       priv->representor_id = repr_port->info.repr_id;
+       priv->dev_data = eth_dev->data;
+       priv->ifindex = repr_port->info.ifindex;
+
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+       eth_dev->data->mac_addrs = priv->mac;
+       if (rte_is_zero_ether_addr(eth_dev->data->mac_addrs)) {
+               ret = xsc_dev_get_mac(priv->xdev, mac.addr_bytes);
+               if (ret != 0) {
+                       PMD_DRV_LOG(ERR, "Port %u cannot get MAC address",
+                                   eth_dev->data->port_id);
+                       return -ENODEV;
+               }
+       }
+
+       xsc_ethdev_mac_addr_add(eth_dev, &mac, 0);
+
+       config->hw_csum = 1;
+       config->pph_flag =  priv->xdev->devargs.pph_mode;
+       if ((config->pph_flag & XSC_TX_PPH) != 0) {
+               config->tso = 0;
+       } else {
+               config->tso = 1;
+               if (config->tso)
+                       config->tso_max_payload_sz = 1500;
+       }
+
+       priv->is_representor = (priv->eth_type == RTE_ETH_REPRESENTOR_NONE) ? 0 
: 1;
+       if (priv->is_representor) {
+               eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
+               eth_dev->data->representor_id = priv->representor_id;
+               eth_dev->data->backer_port_id = eth_dev->data->port_id;
+       }
+
+       eth_dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
+       eth_dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
+
+       rte_eth_dev_probing_finish(eth_dev);
+
+       return 0;
+}
+
+static int
+xsc_ethdev_init_representors(struct rte_eth_dev *eth_dev)
+{
+       struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
+       struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
+       struct rte_device *dev;
+       struct xsc_dev *xdev;
+       struct xsc_repr_port *repr_port;
+       char name[RTE_ETH_NAME_MAX_LEN];
+       int i;
+       int ret;
+
+       PMD_INIT_FUNC_TRACE();
+
+       dev = &priv->pci_dev->device;
+       if (dev->devargs != NULL) {
+               ret = rte_eth_devargs_parse(dev->devargs->args, &eth_da, 1);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to parse device arguments: %s",
+                                   dev->devargs->args);
+                       return -EINVAL;
+               }
+       }
+
+       xdev = priv->xdev;
+       ret = xsc_dev_repr_ports_probe(xdev, eth_da.nb_representor_ports, 
RTE_MAX_ETHPORTS);
+       if (ret != 0) {
+               PMD_DRV_LOG(ERR, "Failed to probe %d xsc device representors",
+                           eth_da.nb_representor_ports);
+               return ret;
+       }
+
+       /* PF rep init */
+       repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
+       ret = xsc_ethdev_init_one_representor(eth_dev, repr_port);
+       if (ret != 0) {
+               PMD_DRV_LOG(ERR, "Failed to init backing representor");
+               return ret;
+       }
+
+       /* VF rep init */
+       for (i = 0; i < eth_da.nb_representor_ports; i++) {
+               repr_port = &xdev->repr_ports[i];
+               snprintf(name, sizeof(name), "%s_rep_%d",
+                        xdev->name, repr_port->info.repr_id);
+               ret = rte_eth_dev_create(dev,
+                                        name,
+                                        sizeof(struct xsc_ethdev_priv),
+                                        NULL, NULL,
+                                        xsc_ethdev_init_one_representor,
+                                        repr_port);
+               if (ret != 0) {
+                       PMD_DRV_LOG(ERR, "Failed to create representor: %d", i);
+                       goto destroy_reprs;
+               }
+       }
+
+       return 0;
+
+destroy_reprs:
+       /* Destroy vf reprs */
+       while ((i--) > 1) {
+               repr_port = &xdev->repr_ports[i];
+               rte_eth_dev_destroy((struct rte_eth_dev *)repr_port->drv_data, 
NULL);
+       }
+
+       /* Destroy pf repr */
+       repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
+       rte_eth_dev_destroy((struct rte_eth_dev *)repr_port->drv_data, NULL);
+       return ret;
+}
+
 static int
 xsc_ethdev_init(struct rte_eth_dev *eth_dev)
 {
@@ -27,7 +187,17 @@ xsc_ethdev_init(struct rte_eth_dev *eth_dev)
        }
        priv->xdev->port_id = eth_dev->data->port_id;
 
+       ret = xsc_ethdev_init_representors(eth_dev);
+       if (ret != 0) {
+               PMD_DRV_LOG(ERR, "Failed to initialize representors");
+               goto uninit_xsc_dev;
+       }
+
        return 0;
+
+uninit_xsc_dev:
+       xsc_dev_uninit(priv->xdev);
+       return ret;
 }
 
 static int
diff --git a/drivers/net/xsc/xsc_ethdev.h b/drivers/net/xsc/xsc_ethdev.h
index 05040f8865..7d161bd22e 100644
--- a/drivers/net/xsc/xsc_ethdev.h
+++ b/drivers/net/xsc/xsc_ethdev.h
@@ -11,6 +11,25 @@ struct xsc_ethdev_priv {
        struct rte_eth_dev *eth_dev;
        struct rte_pci_device *pci_dev;
        struct xsc_dev *xdev;
+       struct xsc_repr_port *repr_port;
+       struct xsc_dev_config config;
+       struct rte_eth_dev_data *dev_data;
+       struct rte_ether_addr mac[XSC_MAX_MAC_ADDRESSES];
+       struct rte_eth_rss_conf rss_conf;
+
+       int representor_id;
+       uint32_t ifindex;
+       uint16_t mtu;
+       uint8_t isolated;
+       uint8_t is_representor;
+
+       uint32_t mode:7;
+       uint32_t member_bitmap:8;
+       uint32_t funcid_type:3;
+       uint32_t funcid:14;
+
+       uint16_t eth_type;
+       uint16_t qp_set_id;
 };
 
 #define TO_XSC_ETHDEV_PRIV(dev) ((struct xsc_ethdev_priv 
*)(dev)->data->dev_private)
-- 
2.25.1

Reply via email to