From 7a2926198f8a3a93ca2452af0146c698e34bf7f7 Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Thu, 24 Sep 2020 09:32:09 +0530 Subject: [PATCH] bus/dpaa: enhance link status This patch adds support to get/set link speed, duplex and autoneg mode status from/to PHY. Enhance device capabilities to advertise all supported link speeds according to mac type. Also enables fallback support for get link status API where kernel support is missing. Signed-off-by: Sachin Saxena Signed-off-by: Rohit Raj Acked-by: Nipun Gupta --- drivers/bus/dpaa/base/qbman/process.c | 123 +++++++++++++++++++--- drivers/bus/dpaa/include/process.h | 34 +++++- drivers/bus/dpaa/rte_bus_dpaa_version.map | 3 + drivers/net/dpaa/dpaa_ethdev.c | 113 ++++++++++++++++---- 4 files changed, 241 insertions(+), 32 deletions(-) diff --git a/drivers/bus/dpaa/base/qbman/process.c b/drivers/bus/dpaa/base/qbman/process.c index 6f7e37957a..9bc92681cd 100644 --- a/drivers/bus/dpaa/base/qbman/process.c +++ b/drivers/bus/dpaa/base/qbman/process.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "process.h" @@ -341,30 +342,78 @@ int dpaa_intr_disable(char *if_name) return 0; } +#define DPAA_IOCTL_GET_IOCTL_VERSION \ + _IOR(DPAA_IOCTL_MAGIC, 0x14, int) + +int dpaa_get_ioctl_version_number(void) +{ + int version_num, ret = check_fd(); + + if (ret) + return ret; + + ret = ioctl(fd, DPAA_IOCTL_GET_IOCTL_VERSION, &version_num); + if (ret) { + if (errno == EINVAL) { + version_num = 1; + } else { + printf("Failed to get ioctl version number\n"); + version_num = -1; + } + } + + return version_num; +} + #define DPAA_IOCTL_GET_LINK_STATUS \ _IOWR(DPAA_IOCTL_MAGIC, 0x10, struct usdpaa_ioctl_link_status_args) -int dpaa_get_link_status(char *if_name) +#define DPAA_IOCTL_GET_LINK_STATUS_OLD \ + _IOWR(DPAA_IOCTL_MAGIC, 0x10, struct usdpaa_ioctl_link_status_args_old) + + +int dpaa_get_link_status(char *if_name, struct rte_eth_link *link) { - int ret = check_fd(); - struct usdpaa_ioctl_link_status_args args; + int ioctl_version, ret = check_fd(); if (ret) return ret; - strcpy(args.if_name, if_name); - args.link_status = 0; + ioctl_version = dpaa_get_ioctl_version_number(); - ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS, &args); - if (ret) { - if (errno == EINVAL) - printf("Failed to get link status: Not Supported\n"); - else + if (ioctl_version == 2) { + struct usdpaa_ioctl_link_status_args args; + + strcpy(args.if_name, if_name); + + ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS, &args); + if (ret) { printf("Failed to get link status\n"); - return ret; + return ret; + } + + link->link_status = args.link_status; + link->link_speed = args.link_speed; + link->link_duplex = args.link_duplex; + link->link_autoneg = args.link_autoneg; + } else { + struct usdpaa_ioctl_link_status_args_old args; + + strcpy(args.if_name, if_name); + + ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS_OLD, &args); + if (ret) { + if (errno == EINVAL) + printf("Get link status: Not Supported\n"); + else + printf("Failed to get link status\n"); + return ret; + } + + link->link_status = args.link_status; } - return args.link_status; + return 0; } #define DPAA_IOCTL_UPDATE_LINK_STATUS \ @@ -393,3 +442,53 @@ int dpaa_update_link_status(char *if_name, int link_status) return 0; } + +#define DPAA_IOCTL_UPDATE_LINK_SPEED \ + _IOW(DPAA_IOCTL_MAGIC, 0x12, struct usdpaa_ioctl_update_link_speed) + +int dpaa_update_link_speed(char *if_name, int link_speed, int link_duplex) +{ + struct usdpaa_ioctl_update_link_speed args; + int ret; + + ret = check_fd(); + if (ret) + return ret; + + strcpy(args.if_name, if_name); + args.link_speed = link_speed; + args.link_duplex = link_duplex; + + ret = ioctl(fd, DPAA_IOCTL_UPDATE_LINK_SPEED, &args); + if (ret) { + if (errno == EINVAL) + printf("Failed to set link speed: Not Supported\n"); + else + printf("Failed to set link speed\n"); + return ret; + } + + return ret; +} + +#define DPAA_IOCTL_RESTART_LINK_AUTONEG \ + _IOW(DPAA_IOCTL_MAGIC, 0x13, char *) + +int dpaa_restart_link_autoneg(char *if_name) +{ + int ret = check_fd(); + + if (ret) + return ret; + + ret = ioctl(fd, DPAA_IOCTL_RESTART_LINK_AUTONEG, &if_name); + if (ret) { + if (errno == EINVAL) + printf("Failed to restart autoneg: Not Supported\n"); + else + printf("Failed to restart autoneg\n"); + return ret; + } + + return ret; +} diff --git a/drivers/bus/dpaa/include/process.h b/drivers/bus/dpaa/include/process.h index f52ea16358..be52e6f72d 100644 --- a/drivers/bus/dpaa/include/process.h +++ b/drivers/bus/dpaa/include/process.h @@ -10,6 +10,7 @@ #define __PROCESS_H #include +#include /* The process device underlies process-wide user/kernel interactions, such as * mapping dma_mem memory and providing accompanying ioctl()s. (This isn't used @@ -86,10 +87,25 @@ int dpaa_intr_enable(char *if_name, int efd); __rte_internal int dpaa_intr_disable(char *if_name); +struct usdpaa_ioctl_link_status_args_old { + /* network device node name */ + char if_name[IF_NAME_MAX_LEN]; + /* link status(ETH_LINK_UP/DOWN) */ + int link_status; +}; + struct usdpaa_ioctl_link_status_args { /* network device node name */ char if_name[IF_NAME_MAX_LEN]; + /* link status(ETH_LINK_UP/DOWN) */ int link_status; + /* link speed (ETH_SPEED_NUM_)*/ + int link_speed; + /* link duplex (ETH_LINK_[HALF/FULL]_DUPLEX)*/ + int link_duplex; + /* link autoneg (ETH_LINK_AUTONEG/FIXED)*/ + int link_autoneg; + }; struct usdpaa_ioctl_update_link_status_args { @@ -99,10 +115,24 @@ struct usdpaa_ioctl_update_link_status_args { int link_status; }; -__rte_internal -int dpaa_get_link_status(char *if_name); +struct usdpaa_ioctl_update_link_speed { + /* network device node name*/ + char if_name[IF_NAME_MAX_LEN]; + /* link speed (ETH_SPEED_NUM_)*/ + int link_speed; + /* link duplex (ETH_LINK_[HALF/FULL]_DUPLEX)*/ + int link_duplex; +}; +__rte_internal +int dpaa_get_link_status(char *if_name, struct rte_eth_link *link); __rte_internal int dpaa_update_link_status(char *if_name, int link_status); +__rte_internal +int dpaa_update_link_speed(char *if_name, int speed, int duplex); +__rte_internal +int dpaa_restart_link_autoneg(char *if_name); +__rte_internal +int dpaa_get_ioctl_version_number(void); #endif /* __PROCESS_H */ diff --git a/drivers/bus/dpaa/rte_bus_dpaa_version.map b/drivers/bus/dpaa/rte_bus_dpaa_version.map index f6028b82de..9bd2601213 100644 --- a/drivers/bus/dpaa/rte_bus_dpaa_version.map +++ b/drivers/bus/dpaa/rte_bus_dpaa_version.map @@ -8,10 +8,13 @@ INTERNAL { bman_query_free_buffers; bman_release; bman_thread_irq; + dpaa_get_ioctl_version_number; dpaa_get_eth_port_cfg; dpaa_get_qm_channel_caam; dpaa_get_qm_channel_pool; dpaa_get_link_status; + dpaa_restart_link_autoneg; + dpaa_update_link_speed; dpaa_intr_disable; dpaa_intr_enable; dpaa_svr_family; diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c index 5c2acea3d4..af47c196ae 100644 --- a/drivers/net/dpaa/dpaa_ethdev.c +++ b/drivers/net/dpaa/dpaa_ethdev.c @@ -205,10 +205,12 @@ dpaa_eth_dev_configure(struct rte_eth_dev *dev) uint64_t rx_offloads = eth_conf->rxmode.offloads; uint64_t tx_offloads = eth_conf->txmode.offloads; struct rte_device *rdev = dev->device; + struct rte_eth_link *link = &dev->data->dev_link; struct rte_dpaa_device *dpaa_dev; struct fman_if *fif = dev->process_private; struct __fman_if *__fif; struct rte_intr_handle *intr_handle; + int speed, duplex; int ret; PMD_INIT_FUNC_TRACE(); @@ -292,6 +294,60 @@ dpaa_eth_dev_configure(struct rte_eth_dev *dev) dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC; } } + + /* Wait for link status to get updated */ + if (!link->link_status) + sleep(1); + + /* Configure link only if link is UP*/ + if (link->link_status) { + if (eth_conf->link_speeds == ETH_LINK_SPEED_AUTONEG) { + /* Start autoneg only if link is not in autoneg mode */ + if (!link->link_autoneg) + dpaa_restart_link_autoneg(__fif->node_name); + } else if (eth_conf->link_speeds & ETH_LINK_SPEED_FIXED) { + switch (eth_conf->link_speeds & ~ETH_LINK_SPEED_FIXED) { + case ETH_LINK_SPEED_10M_HD: + speed = ETH_SPEED_NUM_10M; + duplex = ETH_LINK_HALF_DUPLEX; + break; + case ETH_LINK_SPEED_10M: + speed = ETH_SPEED_NUM_10M; + duplex = ETH_LINK_FULL_DUPLEX; + break; + case ETH_LINK_SPEED_100M_HD: + speed = ETH_SPEED_NUM_100M; + duplex = ETH_LINK_HALF_DUPLEX; + break; + case ETH_LINK_SPEED_100M: + speed = ETH_SPEED_NUM_100M; + duplex = ETH_LINK_FULL_DUPLEX; + break; + case ETH_LINK_SPEED_1G: + speed = ETH_SPEED_NUM_1G; + duplex = ETH_LINK_FULL_DUPLEX; + break; + case ETH_LINK_SPEED_2_5G: + speed = ETH_SPEED_NUM_2_5G; + duplex = ETH_LINK_FULL_DUPLEX; + break; + case ETH_LINK_SPEED_10G: + speed = ETH_SPEED_NUM_10G; + duplex = ETH_LINK_FULL_DUPLEX; + break; + default: + speed = ETH_SPEED_NUM_NONE; + duplex = ETH_LINK_FULL_DUPLEX; + break; + } + /* Set link speed */ + dpaa_update_link_speed(__fif->node_name, speed, duplex); + } else { + /* Manual autoneg - custom advertisement speed. */ + printf("Custom Advertisement speeds not supported\n"); + } + } + return 0; } @@ -377,6 +433,7 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev) struct rte_device *rdev = dev->device; struct rte_dpaa_device *dpaa_dev; struct rte_intr_handle *intr_handle; + struct rte_eth_link *link = &dev->data->dev_link; struct dpaa_if *dpaa_intf = dev->data->dev_private; int loop; @@ -402,6 +459,10 @@ static int dpaa_eth_dev_close(struct rte_eth_dev *dev) dpaa_eth_dev_stop(dev); + /* Reset link to autoneg */ + if (link->link_status && !link->link_autoneg) + dpaa_restart_link_autoneg(__fif->node_name); + if (intr_handle && intr_handle->fd && dev->data->dev_conf.intr_conf.lsc != 0) { dpaa_intr_disable(__fif->node_name); @@ -500,12 +561,24 @@ static int dpaa_eth_dev_info(struct rte_eth_dev *dev, dev_info->flow_type_rss_offloads = DPAA_RSS_OFFLOAD_ALL; if (fif->mac_type == fman_mac_1g) { - dev_info->speed_capa = ETH_LINK_SPEED_1G; + dev_info->speed_capa = ETH_LINK_SPEED_10M_HD + | ETH_LINK_SPEED_10M + | ETH_LINK_SPEED_100M_HD + | ETH_LINK_SPEED_100M + | ETH_LINK_SPEED_1G; } else if (fif->mac_type == fman_mac_2_5g) { - dev_info->speed_capa = ETH_LINK_SPEED_1G + dev_info->speed_capa = ETH_LINK_SPEED_10M_HD + | ETH_LINK_SPEED_10M + | ETH_LINK_SPEED_100M_HD + | ETH_LINK_SPEED_100M + | ETH_LINK_SPEED_1G | ETH_LINK_SPEED_2_5G; } else if (fif->mac_type == fman_mac_10g) { - dev_info->speed_capa = ETH_LINK_SPEED_1G + dev_info->speed_capa = ETH_LINK_SPEED_10M_HD + | ETH_LINK_SPEED_10M + | ETH_LINK_SPEED_100M_HD + | ETH_LINK_SPEED_100M + | ETH_LINK_SPEED_1G | ETH_LINK_SPEED_2_5G | ETH_LINK_SPEED_10G; } else { @@ -602,31 +675,35 @@ static int dpaa_eth_link_update(struct rte_eth_dev *dev, struct rte_eth_link *link = &dev->data->dev_link; struct fman_if *fif = dev->process_private; struct __fman_if *__fif = container_of(fif, struct __fman_if, __if); - int ret; + int ret, ioctl_version; PMD_INIT_FUNC_TRACE(); - if (fif->mac_type == fman_mac_1g) - link->link_speed = ETH_SPEED_NUM_1G; - else if (fif->mac_type == fman_mac_2_5g) - link->link_speed = ETH_SPEED_NUM_2_5G; - else if (fif->mac_type == fman_mac_10g) - link->link_speed = ETH_SPEED_NUM_10G; - else - DPAA_PMD_ERR("invalid link_speed: %s, %d", - dpaa_intf->name, fif->mac_type); + ioctl_version = dpaa_get_ioctl_version_number(); + if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) { - ret = dpaa_get_link_status(__fif->node_name); - if (ret < 0) + ret = dpaa_get_link_status(__fif->node_name, link); + if (ret) return ret; - link->link_status = ret; } else { link->link_status = dpaa_intf->valid; } - link->link_duplex = ETH_LINK_FULL_DUPLEX; - link->link_autoneg = ETH_LINK_AUTONEG; + if (ioctl_version < 2) { + link->link_duplex = ETH_LINK_FULL_DUPLEX; + link->link_autoneg = ETH_LINK_AUTONEG; + + if (fif->mac_type == fman_mac_1g) + link->link_speed = ETH_SPEED_NUM_1G; + else if (fif->mac_type == fman_mac_2_5g) + link->link_speed = ETH_SPEED_NUM_2_5G; + else if (fif->mac_type == fman_mac_10g) + link->link_speed = ETH_SPEED_NUM_10G; + else + DPAA_PMD_ERR("invalid link_speed: %s, %d", + dpaa_intf->name, fif->mac_type); + } DPAA_PMD_INFO("Port %d Link is %s\n", dev->data->port_id, link->link_status ? "Up" : "Down"); -- 2.20.1