@@ -8,6 +8,10 @@
#define XSC_PCI_VENDOR_ID 0x1f67
#define XSC_PCI_DEV_ID_MS 0x1111
+#define XSC_VFREP_BASE_LOGICAL_PORT 1081
+
+
+
enum xsc_nic_mode {
XSC_NIC_MODE_LEGACY,
XSC_NIC_MODE_SWITCHDEV,
@@ -31,5 +35,25 @@ enum xsc_flow_mode {
XSC_FLOW_MODE_MAX,
};
+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_phy_port_type {
+ XSC_PORT_TYPE_NONE = 0,
+ XSC_PORT_TYPE_UPLINK, /* mac0rep */
+ XSC_PORT_TYPE_UPLINK_BOND, /* bondrep */
+ XSC_PORT_TYPE_PFVF, /*hasreps: vfrep*/
+ XSC_PORT_TYPE_PFHPF, /*hasreps: host pf rep*/
+ XSC_PORT_TYPE_UNKNOWN,
+};
+
+#define XSC_PHY_PORT_NUM 1
+
#endif /* XSC_DEFS_H_ */
@@ -23,6 +23,31 @@
#define XSC_DEV_DEF_FLOW_MODE XSC_FLOW_MODE_NULL
#define XSC_DEV_CTRL_FILE_FMT "/dev/yunsilicon/port_ctrl_" PCI_PRI_FMT
+static int
+xsc_dev_alloc_vfos_info(struct xsc_dev *dev)
+{
+ struct xsc_hwinfo *hwinfo;
+ int vfrep_offset = 0;
+ int base_lp = 0;
+
+ hwinfo = &dev->hwinfo;
+ if (hwinfo->pcie_no == 1) {
+ vfrep_offset = hwinfo->func_id -
+ hwinfo->pcie1_pf_funcid_base +
+ hwinfo->pcie0_pf_funcid_top -
+ hwinfo->pcie0_pf_funcid_base + 1;
+ } else {
+ vfrep_offset = hwinfo->func_id - hwinfo->pcie0_pf_funcid_base;
+ }
+
+ base_lp = XSC_VFREP_BASE_LOGICAL_PORT;
+ if (dev->devargs.nic_mode == XSC_NIC_MODE_LEGACY)
+ base_lp = base_lp + vfrep_offset;
+
+ dev->vfos_logical_in_port = base_lp;
+ return 0;
+}
+
static int xsc_hwinfo_init(struct xsc_dev *dev)
{
struct {
@@ -174,6 +199,73 @@ xsc_dev_close(struct xsc_dev *dev)
ibv_close_device(dev->ibv_ctx);
}
+static void
+xsc_repr_info_init(struct xsc_repr_info *info, enum xsc_phy_port_type port_type,
+ enum xsc_funcid_type funcid_type, int32_t repr_id)
+{
+ 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 = XSC_PHYPORT_MAC_FUNCID << 14;
+ } else if (port_type == XSC_PORT_TYPE_PFVF) {
+ info->funcid = funcid_type << 14;
+ }
+}
+
+int
+xsc_repr_ports_probe(struct xsc_dev *dev, int nb_ports, int max_nb_ports)
+{
+ int funcid_type;
+ struct xsc_repr_port *repr_port;
+ int i;
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ ret = xsc_get_ifindex_by_pci_addr(&dev->pci_dev->addr, &dev->ifindex);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Could not get xsc dev ifindex");
+ return ret;
+ }
+
+ dev->num_repr_ports = nb_ports + 1;
+
+ dev->repr_ports = rte_zmalloc(NULL,
+ sizeof(struct xsc_repr_port) * dev->num_repr_ports,
+ RTE_CACHE_LINE_SIZE);
+ if (dev->repr_ports == NULL) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory for repr_ports");
+ return -ENOMEM;
+ }
+
+ funcid_type = (dev->devargs.nic_mode == XSC_NIC_MODE_SWITCHDEV) ?
+ XSC_VF_IOCTL_FUNCID : XSC_PHYPORT_MAC_FUNCID;
+
+ repr_port = &dev->repr_ports[XSC_DEV_REPR_PORT];
+ xsc_repr_info_init(&repr_port->info,
+ XSC_PORT_TYPE_UPLINK, XSC_FUNCID_TYPE_UNKNOWN, -1);
+ repr_port->info.ifindex = dev->ifindex;
+ repr_port->xdev = dev;
+
+ if ((dev->devargs.pph_mode & XSC_TX_PPH) == 0)
+ repr_port->info.repr_id = 510;
+ else
+ repr_port->info.repr_id = max_nb_ports - 1;
+
+ for (i = 1; i < dev->num_repr_ports; i++) {
+ repr_port = &dev->repr_ports[i];
+ xsc_repr_info_init(&repr_port->info,
+ XSC_PORT_TYPE_PFVF, funcid_type, i - XSC_PHY_PORT_NUM);
+ repr_port->xdev = dev;
+ }
+
+ return 0;
+}
+
int
xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **dev)
{
@@ -199,8 +291,15 @@ xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **dev)
ret = xsc_hwinfo_init(d);
if (ret) {
PMD_DRV_LOG(ERR, "Failed to initialize hardware info");
+ ret = -EINVAL;
+ goto hwinfo_init_fail;
+ }
+
+ ret = xsc_dev_alloc_vfos_info(d);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Alloc vfos info failed");
+ ret = -EINVAL;
goto hwinfo_init_fail;
- return ret;
}
d->pci_dev = pci_dev;
@@ -220,6 +319,8 @@ xsc_dev_uninit(struct xsc_dev *dev)
{
PMD_INIT_FUNC_TRACE();
+ if (dev->repr_ports != NULL)
+ rte_free(dev->repr_ports);
xsc_dev_close(dev);
rte_free(dev);
}
@@ -7,10 +7,14 @@
#include <infiniband/verbs.h>
+#include "xsc_defs.h"
+
#define XSC_PPH_MODE_ARG "pph_mode"
#define XSC_NIC_MODE_ARG "nic_mode"
#define XSC_FLOW_MODE_ARG "flow_mode"
+#define XSC_DEV_REPR_PORT 0
+
struct xsc_hwinfo {
uint8_t valid; /* 1: current phy info is valid, 0 : invalid */
uint32_t pcie_no; /* pcie number , 0 or 1 */
@@ -48,10 +52,32 @@ struct xsc_devargs {
int pph_mode;
};
+struct xsc_repr_info {
+ int32_t repr_id;
+ enum xsc_phy_port_type port_type;
+ int pf_bond;
+
+ uint32_t ifindex;
+ const char *phys_dev_name;
+ uint32_t funcid;
+};
+
+struct xsc_repr_port {
+ struct xsc_dev *xdev;
+ struct xsc_repr_info info;
+ void *drv_data;
+};
+
struct xsc_dev {
struct rte_pci_device *pci_dev;
struct xsc_devargs devargs;
struct xsc_hwinfo hwinfo;
+ int vfos_logical_in_port;
+
+ struct xsc_repr_port *repr_ports;
+ int num_repr_ports;
+ int ifindex;
+
struct ibv_context *ibv_ctx;
struct ibv_pd *ibv_pd;
char ibv_name[IBV_SYSFS_NAME_MAX];
@@ -62,5 +88,6 @@ struct xsc_dev {
int xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **dev);
void xsc_dev_uninit(struct xsc_dev *dev);
+int xsc_repr_ports_probe(struct xsc_dev *dev, int nb_port, int max_nb_ports);
#endif /* _XSC_DEV_H_ */
@@ -10,6 +10,9 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
#include <sys/mman.h>
#include "xsc_log.h"
@@ -94,3 +97,122 @@ xsc_get_ibv_device(const struct rte_pci_addr *addr)
return ibv_match;
}
+
+int
+xsc_get_ifname_by_pci_addr(struct rte_pci_addr *addr, char *ifname)
+{
+ DIR *dir;
+ struct dirent *dent;
+ unsigned int dev_type = 0;
+ unsigned int dev_port_prev = ~0u;
+ char match[IF_NAMESIZE] = "";
+ char net_path[PATH_MAX];
+
+ snprintf(net_path, sizeof(net_path), "%s/" PCI_PRI_FMT "/net",
+ rte_pci_get_sysfs_path(), addr->domain, addr->bus,
+ addr->devid, addr->function);
+
+ dir = opendir(net_path);
+ if (dir == NULL) {
+ PMD_DRV_LOG(ERR, "Could not open %s", net_path);
+ return -ENOENT;
+ }
+
+ while ((dent = readdir(dir)) != NULL) {
+ char *name = dent->d_name;
+ FILE *file;
+ unsigned int dev_port;
+ int r;
+ char path[PATH_MAX];
+
+ if ((name[0] == '.') &&
+ ((name[1] == '\0') ||
+ ((name[1] == '.') && (name[2] == '\0'))))
+ continue;
+
+ snprintf(path, sizeof(path), "%s/%s/%s",
+ net_path, name, (dev_type ? "dev_id" : "dev_port"));
+
+ file = fopen(path, "rb");
+ if (file == NULL) {
+ if (errno != ENOENT)
+ continue;
+ /*
+ * Switch to dev_id when dev_port does not exist as
+ * is the case with Linux kernel versions < 3.15.
+ */
+try_dev_id:
+ match[0] = '\0';
+ if (dev_type)
+ break;
+ dev_type = 1;
+ dev_port_prev = ~0u;
+ rewinddir(dir);
+ continue;
+ }
+ r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port);
+ fclose(file);
+ if (r != 1)
+ continue;
+ /*
+ * Switch to dev_id when dev_port returns the same value for
+ * all ports. May happen when using a MOFED release older than
+ * 3.0 with a Linux kernel >= 3.15.
+ */
+ if (dev_port == dev_port_prev)
+ goto try_dev_id;
+ dev_port_prev = dev_port;
+ if (dev_port == 0)
+ snprintf(match, IF_NAMESIZE, "%s", name);
+ }
+ closedir(dir);
+ if (match[0] == '\0')
+ return -ENOENT;
+
+ snprintf(ifname, IF_NAMESIZE, "%s", match);
+ return 0;
+}
+
+int
+xsc_get_ifindex_by_ifname(const char *ifname, int *ifindex)
+{
+ struct ifreq ifr;
+ int sockfd;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd == -1)
+ return -EINVAL;
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
+ if (ioctl(sockfd, SIOCGIFINDEX, &ifr) == -1) {
+ close(sockfd);
+ return -EINVAL;
+ }
+
+ *ifindex = ifr.ifr_ifindex;
+
+ close(sockfd);
+ return 0;
+}
+
+int
+xsc_get_ifindex_by_pci_addr(struct rte_pci_addr *addr, int *ifindex)
+{
+ char ifname[IF_NAMESIZE];
+ int ret;
+
+ ret = xsc_get_ifname_by_pci_addr(addr, ifname);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Could not get ifname by pci address:" PCI_PRI_FMT,
+ addr->domain, addr->bus, addr->devid, addr->function);
+ return ret;
+ }
+
+ ret = xsc_get_ifindex_by_ifname(ifname, ifindex);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Could not get ifindex by ifname:%s", ifname);
+ return ret;
+ }
+
+ return 0;
+}
@@ -10,5 +10,8 @@
#include <ethdev_pci.h>
struct ibv_device *xsc_get_ibv_device(const struct rte_pci_addr *addr);
+int xsc_get_ifname_by_pci_addr(struct rte_pci_addr *addr, char *ifname);
+int xsc_get_ifindex_by_ifname(const char *ifname, int *ifindex);
+int xsc_get_ifindex_by_pci_addr(struct rte_pci_addr *addr, int *ifindex);
#endif /* _XSC_UTILS_H_ */