Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
Show First 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | static const struct { | ||||
[MLX5E_50GBASE_KR2] = { | [MLX5E_50GBASE_KR2] = { | ||||
.subtype = IFM_50G_KR2, | .subtype = IFM_50G_KR2, | ||||
.baudrate = IF_Gbps(50ULL), | .baudrate = IF_Gbps(50ULL), | ||||
}, | }, | ||||
}; | }; | ||||
MALLOC_DEFINE(M_MLX5EN, "MLX5EN", "MLX5 Ethernet"); | MALLOC_DEFINE(M_MLX5EN, "MLX5EN", "MLX5 Ethernet"); | ||||
static SYSCTL_NODE(_hw, OID_AUTO, mlx5, CTLFLAG_RW, 0, "MLX5 driver parameters"); | |||||
static void | static void | ||||
mlx5e_update_carrier(struct mlx5e_priv *priv) | mlx5e_update_carrier(struct mlx5e_priv *priv) | ||||
{ | { | ||||
struct mlx5_core_dev *mdev = priv->mdev; | struct mlx5_core_dev *mdev = priv->mdev; | ||||
u32 out[MLX5_ST_SZ_DW(ptys_reg)]; | u32 out[MLX5_ST_SZ_DW(ptys_reg)]; | ||||
u32 eth_proto_oper; | u32 eth_proto_oper; | ||||
int error; | int error; | ||||
u8 port_state; | u8 port_state; | ||||
▲ Show 20 Lines • Show All 467 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
mlx5e_disable_async_events(struct mlx5e_priv *priv) | mlx5e_disable_async_events(struct mlx5e_priv *priv) | ||||
{ | { | ||||
mtx_lock(&priv->async_events_mtx); | mtx_lock(&priv->async_events_mtx); | ||||
clear_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLE, &priv->state); | clear_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLE, &priv->state); | ||||
mtx_unlock(&priv->async_events_mtx); | mtx_unlock(&priv->async_events_mtx); | ||||
} | } | ||||
static void mlx5e_calibration_callout(void *arg); | |||||
static int mlx5e_calibration_duration = 20; | |||||
static int mlx5e_fast_calibration = 1; | |||||
static int mlx5e_normal_calibration = 30; | |||||
static SYSCTL_NODE(_hw_mlx5, OID_AUTO, calibr, CTLFLAG_RW, 0, | |||||
"MLX5 timestamp calibration parameteres"); | |||||
SYSCTL_INT(_hw_mlx5_calibr, OID_AUTO, duration, CTLFLAG_RWTUN, | |||||
&mlx5e_calibration_duration, 0, | |||||
"Duration of initial calibration"); | |||||
SYSCTL_INT(_hw_mlx5_calibr, OID_AUTO, fast, CTLFLAG_RWTUN, | |||||
&mlx5e_fast_calibration, 0, | |||||
"Recalibration interval during initial calibration"); | |||||
SYSCTL_INT(_hw_mlx5_calibr, OID_AUTO, normal, CTLFLAG_RWTUN, | |||||
&mlx5e_normal_calibration, 0, | |||||
"Recalibration interval during normal operations"); | |||||
/* | |||||
* Ignites the calibration process. | |||||
*/ | |||||
static void | |||||
mlx5e_reset_calibration_callout(struct mlx5e_priv *priv) | |||||
{ | |||||
if (priv->clbr_done == 0) | |||||
mlx5e_calibration_callout(priv); | |||||
else | |||||
callout_reset_curcpu(&priv->tstmp_clbr, (priv->clbr_done < | |||||
mlx5e_calibration_duration ? mlx5e_fast_calibration : | |||||
mlx5e_normal_calibration) * hz, mlx5e_calibration_callout, | |||||
priv); | |||||
} | |||||
static uint64_t | |||||
mlx5e_timespec2usec(const struct timespec *ts) | |||||
{ | |||||
return ((uint64_t)ts->tv_sec * 1000000000 + ts->tv_nsec); | |||||
} | |||||
static uint64_t | |||||
mlx5e_hw_clock(struct mlx5e_priv *priv) | |||||
{ | |||||
struct mlx5_init_seg *iseg; | |||||
uint32_t hw_h, hw_h1, hw_l; | |||||
iseg = priv->mdev->iseg; | |||||
do { | |||||
hw_h = ioread32be(&iseg->internal_timer_h); | |||||
hw_l = ioread32be(&iseg->internal_timer_l); | |||||
hw_h1 = ioread32be(&iseg->internal_timer_h); | |||||
} while (hw_h1 != hw_h); | |||||
return (((uint64_t)hw_h << 32) | hw_l); | |||||
} | |||||
/* | |||||
* The calibration callout, it runs either in the context of the | |||||
* thread which enables calibration, or in callout. It takes the | |||||
* snapshot of system and adapter clocks, then advances the pointers to | |||||
* the calibration point to allow rx path to read the consistent data | |||||
* lockless. | |||||
*/ | |||||
static void | |||||
mlx5e_calibration_callout(void *arg) | |||||
{ | |||||
struct mlx5e_priv *priv; | |||||
struct mlx5e_clbr_point *next, *curr; | |||||
struct timespec ts; | |||||
int clbr_curr_next; | |||||
priv = arg; | |||||
curr = &priv->clbr_points[priv->clbr_curr]; | |||||
clbr_curr_next = priv->clbr_curr + 1; | |||||
if (clbr_curr_next >= nitems(priv->clbr_points)) | |||||
clbr_curr_next = 0; | |||||
next = &priv->clbr_points[clbr_curr_next]; | |||||
next->base_prev = curr->base_curr; | |||||
next->clbr_hw_prev = curr->clbr_hw_curr; | |||||
next->clbr_hw_curr = mlx5e_hw_clock(priv); | |||||
if (((next->clbr_hw_curr - curr->clbr_hw_prev) >> MLX5E_TSTMP_PREC) == | |||||
0) { | |||||
if_printf(priv->ifp, "HW failed tstmp frozen %#jx %#jx," | |||||
"disabling\n", next->clbr_hw_curr, curr->clbr_hw_prev); | |||||
priv->clbr_done = 0; | |||||
return; | |||||
} | |||||
nanouptime(&ts); | |||||
next->base_curr = mlx5e_timespec2usec(&ts); | |||||
curr->clbr_gen = 0; | |||||
atomic_thread_fence_rel(); | |||||
priv->clbr_curr = clbr_curr_next; | |||||
atomic_store_rel_int(&next->clbr_gen, ++(priv->clbr_gen)); | |||||
if (priv->clbr_done < mlx5e_calibration_duration) | |||||
priv->clbr_done++; | |||||
mlx5e_reset_calibration_callout(priv); | |||||
} | |||||
static const char *mlx5e_rq_stats_desc[] = { | static const char *mlx5e_rq_stats_desc[] = { | ||||
MLX5E_RQ_STATS(MLX5E_STATS_DESC) | MLX5E_RQ_STATS(MLX5E_STATS_DESC) | ||||
}; | }; | ||||
static int | static int | ||||
mlx5e_create_rq(struct mlx5e_channel *c, | mlx5e_create_rq(struct mlx5e_channel *c, | ||||
struct mlx5e_rq_param *param, | struct mlx5e_rq_param *param, | ||||
struct mlx5e_rq *rq) | struct mlx5e_rq *rq) | ||||
▲ Show 20 Lines • Show All 2,040 Lines • ▼ Show 20 Lines | if (mask & IFCAP_LRO) { | ||||
priv->params_ethtool.hw_lro = priv->params.hw_lro_en; | priv->params_ethtool.hw_lro = priv->params.hw_lro_en; | ||||
} | } | ||||
} | } | ||||
if (was_opened && need_restart) { | if (was_opened && need_restart) { | ||||
mlx5e_close_locked(ifp); | mlx5e_close_locked(ifp); | ||||
mlx5e_open_locked(ifp); | mlx5e_open_locked(ifp); | ||||
} | } | ||||
} | } | ||||
if (mask & IFCAP_HWRXTSTMP) { | |||||
ifp->if_capenable ^= IFCAP_HWRXTSTMP; | |||||
if (ifp->if_capenable & IFCAP_HWRXTSTMP) { | |||||
if (priv->clbr_done == 0) | |||||
mlx5e_reset_calibration_callout(priv); | |||||
} else { | |||||
callout_drain(&priv->tstmp_clbr); | |||||
priv->clbr_done = 0; | |||||
} | |||||
} | |||||
out: | out: | ||||
PRIV_UNLOCK(priv); | PRIV_UNLOCK(priv); | ||||
break; | break; | ||||
case SIOCGI2C: | case SIOCGI2C: | ||||
ifr = (struct ifreq *)data; | ifr = (struct ifreq *)data; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 489 Lines • ▼ Show 20 Lines | /* | ||||
* Set driver features | * Set driver features | ||||
*/ | */ | ||||
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6; | ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6; | ||||
ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; | ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; | ||||
ifp->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER; | ifp->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER; | ||||
ifp->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU; | ifp->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU; | ||||
ifp->if_capabilities |= IFCAP_LRO; | ifp->if_capabilities |= IFCAP_LRO; | ||||
ifp->if_capabilities |= IFCAP_TSO | IFCAP_VLAN_HWTSO; | ifp->if_capabilities |= IFCAP_TSO | IFCAP_VLAN_HWTSO; | ||||
ifp->if_capabilities |= IFCAP_HWSTATS; | ifp->if_capabilities |= IFCAP_HWSTATS | IFCAP_HWRXTSTMP; | ||||
/* set TSO limits so that we don't have to drop TX packets */ | /* set TSO limits so that we don't have to drop TX packets */ | ||||
ifp->if_hw_tsomax = MLX5E_MAX_TX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN); | ifp->if_hw_tsomax = MLX5E_MAX_TX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN); | ||||
ifp->if_hw_tsomaxsegcount = MLX5E_MAX_TX_MBUF_FRAGS - 1 /* hdr */; | ifp->if_hw_tsomaxsegcount = MLX5E_MAX_TX_MBUF_FRAGS - 1 /* hdr */; | ||||
ifp->if_hw_tsomaxsegsize = MLX5E_MAX_TX_MBUF_SIZE; | ifp->if_hw_tsomaxsegsize = MLX5E_MAX_TX_MBUF_SIZE; | ||||
ifp->if_capenable = ifp->if_capabilities; | ifp->if_capenable = ifp->if_capabilities; | ||||
ifp->if_hwassist = 0; | ifp->if_hwassist = 0; | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | mlx5e_create_stats(&priv->stats.pport.ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet), | ||||
priv->stats.pport.arg); | priv->stats.pport.arg); | ||||
mlx5e_create_ethtool(priv); | mlx5e_create_ethtool(priv); | ||||
mtx_lock(&priv->async_events_mtx); | mtx_lock(&priv->async_events_mtx); | ||||
mlx5e_update_stats(priv); | mlx5e_update_stats(priv); | ||||
mtx_unlock(&priv->async_events_mtx); | mtx_unlock(&priv->async_events_mtx); | ||||
SYSCTL_ADD_INT(&priv->sysctl_ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet), | |||||
OID_AUTO, "rx_clbr_done", CTLFLAG_RD, | |||||
&priv->clbr_done, 0, | |||||
"RX timestamps calibration state"); | |||||
callout_init(&priv->tstmp_clbr, CALLOUT_DIRECT); | |||||
mlx5e_reset_calibration_callout(priv); | |||||
return (priv); | return (priv); | ||||
err_dealloc_transport_domain: | err_dealloc_transport_domain: | ||||
mlx5_dealloc_transport_domain(mdev, priv->tdn); | mlx5_dealloc_transport_domain(mdev, priv->tdn); | ||||
err_dealloc_pd: | err_dealloc_pd: | ||||
mlx5_core_dealloc_pd(mdev, priv->pdn); | mlx5_core_dealloc_pd(mdev, priv->pdn); | ||||
Show All 27 Lines | mlx5e_destroy_ifp(struct mlx5_core_dev *mdev, void *vpriv) | ||||
*/ | */ | ||||
device_set_desc(mdev->pdev->dev.bsddev, NULL); | device_set_desc(mdev->pdev->dev.bsddev, NULL); | ||||
/* XXX wait a bit to allow IOCTL handlers to complete */ | /* XXX wait a bit to allow IOCTL handlers to complete */ | ||||
pause("W", hz); | pause("W", hz); | ||||
/* stop watchdog timer */ | /* stop watchdog timer */ | ||||
callout_drain(&priv->watchdog); | callout_drain(&priv->watchdog); | ||||
callout_drain(&priv->tstmp_clbr); | |||||
if (priv->vlan_attach != NULL) | if (priv->vlan_attach != NULL) | ||||
EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach); | EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach); | ||||
if (priv->vlan_detach != NULL) | if (priv->vlan_detach != NULL) | ||||
EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach); | EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach); | ||||
/* make sure device gets closed */ | /* make sure device gets closed */ | ||||
PRIV_LOCK(priv); | PRIV_LOCK(priv); | ||||
▲ Show 20 Lines • Show All 61 Lines • Show Last 20 Lines |