#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <rte_ethdev.h>
#include "process.h"
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 \
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;
+}
#define __PROCESS_H
#include <compat.h>
+#include <rte_ethdev.h>
/* The process device underlies process-wide user/kernel interactions, such as
* mapping dma_mem memory and providing accompanying ioctl()s. (This isn't used
__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 {
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 */
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();
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;
}
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;
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);
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 {
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");