net/sfc: retrieve link info
Signed-off-by: Artem Andreev <artem.andreev@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
03ed21195d
commit
886f8d8a05
@ -4,6 +4,7 @@
|
|||||||
; Refer to default.ini for the full list of available PMD features.
|
; Refer to default.ini for the full list of available PMD features.
|
||||||
;
|
;
|
||||||
[Features]
|
[Features]
|
||||||
|
Link status = Y
|
||||||
BSD nic_uio = Y
|
BSD nic_uio = Y
|
||||||
Linux UIO = Y
|
Linux UIO = Y
|
||||||
Linux VFIO = Y
|
Linux VFIO = Y
|
||||||
|
@ -44,6 +44,8 @@ SFC EFX PMD has support for:
|
|||||||
|
|
||||||
- Multiple transmit and receive queues
|
- Multiple transmit and receive queues
|
||||||
|
|
||||||
|
- Link state information
|
||||||
|
|
||||||
|
|
||||||
Non-supported Features
|
Non-supported Features
|
||||||
----------------------
|
----------------------
|
||||||
|
@ -37,6 +37,8 @@ CFLAGS += -I$(SRCDIR)/base/
|
|||||||
CFLAGS += -I$(SRCDIR)
|
CFLAGS += -I$(SRCDIR)
|
||||||
CFLAGS += -O3
|
CFLAGS += -O3
|
||||||
CFLAGS += $(WERROR_FLAGS)
|
CFLAGS += $(WERROR_FLAGS)
|
||||||
|
# Strict-aliasing rules are violated by rte_eth_link to uint64_t casts
|
||||||
|
CFLAGS += -Wno-strict-aliasing
|
||||||
|
|
||||||
# Enable extra warnings
|
# Enable extra warnings
|
||||||
CFLAGS += -Wextra
|
CFLAGS += -Wextra
|
||||||
|
@ -218,6 +218,9 @@ int sfc_port_init(struct sfc_adapter *sa);
|
|||||||
void sfc_port_fini(struct sfc_adapter *sa);
|
void sfc_port_fini(struct sfc_adapter *sa);
|
||||||
int sfc_port_start(struct sfc_adapter *sa);
|
int sfc_port_start(struct sfc_adapter *sa);
|
||||||
void sfc_port_stop(struct sfc_adapter *sa);
|
void sfc_port_stop(struct sfc_adapter *sa);
|
||||||
|
void sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
|
||||||
|
struct rte_eth_link *link_info);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "sfc_debug.h"
|
#include "sfc_debug.h"
|
||||||
#include "sfc_log.h"
|
#include "sfc_log.h"
|
||||||
#include "sfc_kvargs.h"
|
#include "sfc_kvargs.h"
|
||||||
|
#include "sfc_ev.h"
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -99,6 +100,46 @@ sfc_dev_start(struct rte_eth_dev *dev)
|
|||||||
return -rc;
|
return -rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sfc_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
|
||||||
|
{
|
||||||
|
struct sfc_adapter *sa = dev->data->dev_private;
|
||||||
|
struct rte_eth_link *dev_link = &dev->data->dev_link;
|
||||||
|
struct rte_eth_link old_link;
|
||||||
|
struct rte_eth_link current_link;
|
||||||
|
|
||||||
|
sfc_log_init(sa, "entry");
|
||||||
|
|
||||||
|
if (sa->state != SFC_ADAPTER_STARTED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
|
||||||
|
*(int64_t *)&old_link = rte_atomic64_read((rte_atomic64_t *)dev_link);
|
||||||
|
|
||||||
|
if (wait_to_complete) {
|
||||||
|
efx_link_mode_t link_mode;
|
||||||
|
|
||||||
|
efx_port_poll(sa->nic, &link_mode);
|
||||||
|
sfc_port_link_mode_to_info(link_mode, ¤t_link);
|
||||||
|
|
||||||
|
if (!rte_atomic64_cmpset((volatile uint64_t *)dev_link,
|
||||||
|
*(uint64_t *)&old_link,
|
||||||
|
*(uint64_t *)¤t_link))
|
||||||
|
goto retry;
|
||||||
|
} else {
|
||||||
|
sfc_ev_mgmt_qpoll(sa);
|
||||||
|
*(int64_t *)¤t_link =
|
||||||
|
rte_atomic64_read((rte_atomic64_t *)dev_link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_link.link_status != current_link.link_status)
|
||||||
|
sfc_info(sa, "Link status is %s",
|
||||||
|
current_link.link_status ? "UP" : "DOWN");
|
||||||
|
|
||||||
|
return old_link.link_status == current_link.link_status ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sfc_dev_stop(struct rte_eth_dev *dev)
|
sfc_dev_stop(struct rte_eth_dev *dev)
|
||||||
{
|
{
|
||||||
@ -146,6 +187,7 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
|
|||||||
.dev_start = sfc_dev_start,
|
.dev_start = sfc_dev_start,
|
||||||
.dev_stop = sfc_dev_stop,
|
.dev_stop = sfc_dev_stop,
|
||||||
.dev_close = sfc_dev_close,
|
.dev_close = sfc_dev_close,
|
||||||
|
.link_update = sfc_dev_link_update,
|
||||||
.dev_infos_get = sfc_dev_infos_get,
|
.dev_infos_get = sfc_dev_infos_get,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -181,13 +181,19 @@ sfc_ev_timer(void *arg, uint32_t index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static boolean_t
|
static boolean_t
|
||||||
sfc_ev_link_change(void *arg, __rte_unused efx_link_mode_t link_mode)
|
sfc_ev_link_change(void *arg, efx_link_mode_t link_mode)
|
||||||
{
|
{
|
||||||
struct sfc_evq *evq = arg;
|
struct sfc_evq *evq = arg;
|
||||||
|
struct sfc_adapter *sa = evq->sa;
|
||||||
|
struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
|
||||||
|
struct rte_eth_link new_link;
|
||||||
|
|
||||||
sfc_err(evq->sa, "EVQ %u unexpected link change",
|
EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
|
||||||
evq->evq_index);
|
|
||||||
return B_TRUE;
|
sfc_port_link_mode_to_info(link_mode, &new_link);
|
||||||
|
rte_atomic64_set((rte_atomic64_t *)dev_link, *(uint64_t *)&new_link);
|
||||||
|
|
||||||
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const efx_ev_callbacks_t sfc_ev_callbacks = {
|
static const efx_ev_callbacks_t sfc_ev_callbacks = {
|
||||||
|
@ -129,3 +129,61 @@ sfc_port_fini(struct sfc_adapter *sa)
|
|||||||
|
|
||||||
sfc_log_init(sa, "done");
|
sfc_log_init(sa, "done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
|
||||||
|
struct rte_eth_link *link_info)
|
||||||
|
{
|
||||||
|
SFC_ASSERT(link_mode < EFX_LINK_NMODES);
|
||||||
|
|
||||||
|
memset(link_info, 0, sizeof(*link_info));
|
||||||
|
if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN))
|
||||||
|
link_info->link_status = ETH_LINK_DOWN;
|
||||||
|
else
|
||||||
|
link_info->link_status = ETH_LINK_UP;
|
||||||
|
|
||||||
|
switch (link_mode) {
|
||||||
|
case EFX_LINK_10HDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_10M;
|
||||||
|
link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_10FDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_10M;
|
||||||
|
link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_100HDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_100M;
|
||||||
|
link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_100FDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_100M;
|
||||||
|
link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_1000HDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_1G;
|
||||||
|
link_info->link_duplex = ETH_LINK_HALF_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_1000FDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_1G;
|
||||||
|
link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_10000FDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_10G;
|
||||||
|
link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||||
|
break;
|
||||||
|
case EFX_LINK_40000FDX:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_40G;
|
||||||
|
link_info->link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SFC_ASSERT(B_FALSE);
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case EFX_LINK_UNKNOWN:
|
||||||
|
case EFX_LINK_DOWN:
|
||||||
|
link_info->link_speed = ETH_SPEED_NUM_NONE;
|
||||||
|
link_info->link_duplex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_info->link_autoneg = ETH_LINK_AUTONEG;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user