Merge branch 'mlx5e-next'
Amir Vadai says:
====================
net/mlx5e: Driver updates 04-Aug-2015
This patchset introduces two features to the ConnectX-4 driver: Patch 8/8
("Support physical port counters") exposes some hardware counters through
ethtool. Rest of the patches are preparation and usage of what we call
light-weight netdev open/close. Some flows that used to be in the ndo_open/stop
are moved to the PCI probe/remove flows - i.e. we will make the netdev
open/close operations more "light-weight".
The benefits of this change are:
1) Reduce the execution time of the stop/open operations.
2) Avoid saving SW shadows of resource configurations that must
persist through stop/open operations (e.g flow table steering
rules), and avoid deleting/applying them from/to the device upon
netdev stop/open.
3) Avoid synchronizing threads that access those resources with the
netdev stop/open threads.
Instead of create/destroy the resource during netdev open/stop, This patchset
changes the behavior such that upon netdev stop, traffic is redirected to a
"Drop RQ" (a RQ that silently drops, at the NIC HW level all incoming traffic).
After redirecting the traffic, RX/TX software resources could be destroyed.
During netdev open, the RX/TX rings are created and traffic is redirected to
the RX rings.
Patchset was applied and tested over commit ba7591d
("ebpf: add skb->hash to
offset map for usage in {cls, act}_bpf or filters")
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
c71b5ad06e
|
@ -138,6 +138,80 @@ struct mlx5e_vport_stats {
|
|||
#define NUM_VPORT_COUNTERS 31
|
||||
};
|
||||
|
||||
static const char pport_strings[][ETH_GSTRING_LEN] = {
|
||||
/* IEEE802.3 counters */
|
||||
"frames_tx",
|
||||
"frames_rx",
|
||||
"check_seq_err",
|
||||
"alignment_err",
|
||||
"octets_tx",
|
||||
"octets_received",
|
||||
"multicast_xmitted",
|
||||
"broadcast_xmitted",
|
||||
"multicast_rx",
|
||||
"broadcast_rx",
|
||||
"in_range_len_errors",
|
||||
"out_of_range_len",
|
||||
"too_long_errors",
|
||||
"symbol_err",
|
||||
"mac_control_tx",
|
||||
"mac_control_rx",
|
||||
"unsupported_op_rx",
|
||||
"pause_ctrl_rx",
|
||||
"pause_ctrl_tx",
|
||||
|
||||
/* RFC2863 counters */
|
||||
"in_octets",
|
||||
"in_ucast_pkts",
|
||||
"in_discards",
|
||||
"in_errors",
|
||||
"in_unknown_protos",
|
||||
"out_octets",
|
||||
"out_ucast_pkts",
|
||||
"out_discards",
|
||||
"out_errors",
|
||||
"in_multicast_pkts",
|
||||
"in_broadcast_pkts",
|
||||
"out_multicast_pkts",
|
||||
"out_broadcast_pkts",
|
||||
|
||||
/* RFC2819 counters */
|
||||
"drop_events",
|
||||
"octets",
|
||||
"pkts",
|
||||
"broadcast_pkts",
|
||||
"multicast_pkts",
|
||||
"crc_align_errors",
|
||||
"undersize_pkts",
|
||||
"oversize_pkts",
|
||||
"fragments",
|
||||
"jabbers",
|
||||
"collisions",
|
||||
"p64octets",
|
||||
"p65to127octets",
|
||||
"p128to255octets",
|
||||
"p256to511octets",
|
||||
"p512to1023octets",
|
||||
"p1024to1518octets",
|
||||
"p1519to2047octets",
|
||||
"p2048to4095octets",
|
||||
"p4096to8191octets",
|
||||
"p8192to10239octets",
|
||||
};
|
||||
|
||||
#define NUM_IEEE_802_3_COUNTERS 19
|
||||
#define NUM_RFC_2863_COUNTERS 13
|
||||
#define NUM_RFC_2819_COUNTERS 21
|
||||
#define NUM_PPORT_COUNTERS (NUM_IEEE_802_3_COUNTERS + \
|
||||
NUM_RFC_2863_COUNTERS + \
|
||||
NUM_RFC_2819_COUNTERS)
|
||||
|
||||
struct mlx5e_pport_stats {
|
||||
__be64 IEEE_802_3_counters[NUM_IEEE_802_3_COUNTERS];
|
||||
__be64 RFC_2863_counters[NUM_RFC_2863_COUNTERS];
|
||||
__be64 RFC_2819_counters[NUM_RFC_2819_COUNTERS];
|
||||
};
|
||||
|
||||
static const char rq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
"packets",
|
||||
"csum_none",
|
||||
|
@ -180,6 +254,7 @@ struct mlx5e_sq_stats {
|
|||
|
||||
struct mlx5e_stats {
|
||||
struct mlx5e_vport_stats vport;
|
||||
struct mlx5e_pport_stats pport;
|
||||
};
|
||||
|
||||
struct mlx5e_params {
|
||||
|
@ -217,6 +292,7 @@ struct mlx5e_cq {
|
|||
struct napi_struct *napi;
|
||||
struct mlx5_core_cq mcq;
|
||||
struct mlx5e_channel *channel;
|
||||
struct mlx5e_priv *priv;
|
||||
|
||||
/* control */
|
||||
struct mlx5_wq_ctrl wq_ctrl;
|
||||
|
@ -240,6 +316,7 @@ struct mlx5e_rq {
|
|||
struct mlx5_wq_ctrl wq_ctrl;
|
||||
u32 rqn;
|
||||
struct mlx5e_channel *channel;
|
||||
struct mlx5e_priv *priv;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
struct mlx5e_tx_skb_cb {
|
||||
|
@ -344,10 +421,10 @@ enum mlx5e_traffic_types {
|
|||
MLX5E_NUM_TT,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5E_RQT_SPREADING = 0,
|
||||
MLX5E_RQT_DEFAULT_RQ = 1,
|
||||
MLX5E_NUM_RQT = 2,
|
||||
enum mlx5e_rqt_ix {
|
||||
MLX5E_INDIRECTION_RQT,
|
||||
MLX5E_SINGLE_RQ_RQT,
|
||||
MLX5E_NUM_RQT,
|
||||
};
|
||||
|
||||
struct mlx5e_eth_addr_info {
|
||||
|
@ -372,10 +449,10 @@ struct mlx5e_eth_addr_db {
|
|||
enum {
|
||||
MLX5E_STATE_ASYNC_EVENTS_ENABLE,
|
||||
MLX5E_STATE_OPENED,
|
||||
MLX5E_STATE_DESTROYING,
|
||||
};
|
||||
|
||||
struct mlx5e_vlan_db {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u32 active_vlans_ft_ix[VLAN_N_VID];
|
||||
u32 untagged_rule_ft_ix;
|
||||
u32 any_vlan_rule_ft_ix;
|
||||
|
@ -399,10 +476,11 @@ struct mlx5e_priv {
|
|||
u32 pdn;
|
||||
u32 tdn;
|
||||
struct mlx5_core_mr mr;
|
||||
struct mlx5e_rq drop_rq;
|
||||
|
||||
struct mlx5e_channel **channel;
|
||||
u32 tisn[MLX5E_MAX_NUM_TC];
|
||||
u32 rqtn;
|
||||
u32 rqtn[MLX5E_NUM_RQT];
|
||||
u32 tirn[MLX5E_NUM_TT];
|
||||
|
||||
struct mlx5e_flow_table ft;
|
||||
|
@ -479,10 +557,9 @@ struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq);
|
|||
|
||||
void mlx5e_update_stats(struct mlx5e_priv *priv);
|
||||
|
||||
int mlx5e_open_flow_table(struct mlx5e_priv *priv);
|
||||
void mlx5e_close_flow_table(struct mlx5e_priv *priv);
|
||||
int mlx5e_create_flow_tables(struct mlx5e_priv *priv);
|
||||
void mlx5e_destroy_flow_tables(struct mlx5e_priv *priv);
|
||||
void mlx5e_init_eth_addr(struct mlx5e_priv *priv);
|
||||
void mlx5e_set_rx_mode_core(struct mlx5e_priv *priv);
|
||||
void mlx5e_set_rx_mode_work(struct work_struct *work);
|
||||
|
||||
int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
|
||||
|
@ -491,8 +568,6 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
|
|||
u16 vid);
|
||||
void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv);
|
||||
void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
|
||||
int mlx5e_add_all_vlan_rules(struct mlx5e_priv *priv);
|
||||
void mlx5e_del_all_vlan_rules(struct mlx5e_priv *priv);
|
||||
|
||||
int mlx5e_open_locked(struct net_device *netdev);
|
||||
int mlx5e_close_locked(struct net_device *netdev);
|
||||
|
|
|
@ -171,7 +171,7 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset)
|
|||
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
return NUM_VPORT_COUNTERS +
|
||||
return NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS +
|
||||
priv->params.num_channels * NUM_RQ_STATS +
|
||||
priv->params.num_channels * priv->params.num_tc *
|
||||
NUM_SQ_STATS;
|
||||
|
@ -200,6 +200,11 @@ static void mlx5e_get_strings(struct net_device *dev,
|
|||
strcpy(data + (idx++) * ETH_GSTRING_LEN,
|
||||
vport_strings[i]);
|
||||
|
||||
/* PPORT counters */
|
||||
for (i = 0; i < NUM_PPORT_COUNTERS; i++)
|
||||
strcpy(data + (idx++) * ETH_GSTRING_LEN,
|
||||
pport_strings[i]);
|
||||
|
||||
/* per channel counters */
|
||||
for (i = 0; i < priv->params.num_channels; i++)
|
||||
for (j = 0; j < NUM_RQ_STATS; j++)
|
||||
|
@ -234,6 +239,9 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
|
|||
for (i = 0; i < NUM_VPORT_COUNTERS; i++)
|
||||
data[idx++] = ((u64 *)&priv->stats.vport)[i];
|
||||
|
||||
for (i = 0; i < NUM_PPORT_COUNTERS; i++)
|
||||
data[idx++] = be64_to_cpu(((__be64 *)&priv->stats.pport)[i]);
|
||||
|
||||
/* per channel counters */
|
||||
for (i = 0; i < priv->params.num_channels; i++)
|
||||
for (j = 0; j < NUM_RQ_STATS; j++)
|
||||
|
|
|
@ -594,44 +594,28 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
|
|||
|
||||
void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
|
||||
{
|
||||
WARN_ON(!mutex_is_locked(&priv->state_lock));
|
||||
if (!priv->vlan.filter_disabled)
|
||||
return;
|
||||
|
||||
if (priv->vlan.filter_disabled) {
|
||||
priv->vlan.filter_disabled = false;
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
|
||||
0);
|
||||
}
|
||||
priv->vlan.filter_disabled = false;
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
|
||||
}
|
||||
|
||||
void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
|
||||
{
|
||||
WARN_ON(!mutex_is_locked(&priv->state_lock));
|
||||
if (priv->vlan.filter_disabled)
|
||||
return;
|
||||
|
||||
if (!priv->vlan.filter_disabled) {
|
||||
priv->vlan.filter_disabled = true;
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
|
||||
0);
|
||||
}
|
||||
priv->vlan.filter_disabled = true;
|
||||
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
|
||||
}
|
||||
|
||||
int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
|
||||
u16 vid)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
set_bit(vid, priv->vlan.active_vlans);
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID,
|
||||
vid);
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
return mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
|
||||
}
|
||||
|
||||
int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
|
||||
|
@ -639,56 +623,11 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
|
|||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
clear_bit(vid, priv->vlan.active_vlans);
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5e_add_all_vlan_rules(struct mlx5e_priv *priv)
|
||||
{
|
||||
u16 vid;
|
||||
int err;
|
||||
|
||||
for_each_set_bit(vid, priv->vlan.active_vlans, VLAN_N_VID) {
|
||||
err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID,
|
||||
vid);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (priv->vlan.filter_disabled) {
|
||||
err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
|
||||
0);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5e_del_all_vlan_rules(struct mlx5e_priv *priv)
|
||||
{
|
||||
u16 vid;
|
||||
|
||||
if (priv->vlan.filter_disabled)
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
|
||||
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
|
||||
|
||||
for_each_set_bit(vid, priv->vlan.active_vlans, VLAN_N_VID)
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
|
||||
}
|
||||
|
||||
#define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
|
||||
for (i = 0; i < MLX5E_ETH_ADDR_HASH_SIZE; i++) \
|
||||
hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
|
||||
|
@ -752,18 +691,21 @@ static void mlx5e_handle_netdev_addr(struct mlx5e_priv *priv)
|
|||
mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.netdev_mc, i)
|
||||
hn->action = MLX5E_ACTION_DEL;
|
||||
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
if (!test_bit(MLX5E_STATE_DESTROYING, &priv->state))
|
||||
mlx5e_sync_netdev_addr(priv);
|
||||
|
||||
mlx5e_apply_netdev_addr(priv);
|
||||
}
|
||||
|
||||
void mlx5e_set_rx_mode_core(struct mlx5e_priv *priv)
|
||||
void mlx5e_set_rx_mode_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
|
||||
set_rx_mode_work);
|
||||
|
||||
struct mlx5e_eth_addr_db *ea = &priv->eth_addr;
|
||||
struct net_device *ndev = priv->netdev;
|
||||
|
||||
bool rx_mode_enable = test_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
bool rx_mode_enable = !test_bit(MLX5E_STATE_DESTROYING, &priv->state);
|
||||
bool promisc_enabled = rx_mode_enable && (ndev->flags & IFF_PROMISC);
|
||||
bool allmulti_enabled = rx_mode_enable && (ndev->flags & IFF_ALLMULTI);
|
||||
bool broadcast_enabled = rx_mode_enable;
|
||||
|
@ -796,17 +738,6 @@ void mlx5e_set_rx_mode_core(struct mlx5e_priv *priv)
|
|||
ea->broadcast_enabled = broadcast_enabled;
|
||||
}
|
||||
|
||||
void mlx5e_set_rx_mode_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
|
||||
set_rx_mode_work);
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
mlx5e_set_rx_mode_core(priv);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
}
|
||||
|
||||
void mlx5e_init_eth_addr(struct mlx5e_priv *priv)
|
||||
{
|
||||
ether_addr_copy(priv->eth_addr.broadcast.addr, priv->netdev->broadcast);
|
||||
|
@ -929,7 +860,7 @@ static void mlx5e_destroy_vlan_flow_table(struct mlx5e_priv *priv)
|
|||
mlx5_destroy_flow_table(priv->ft.vlan);
|
||||
}
|
||||
|
||||
int mlx5e_open_flow_table(struct mlx5e_priv *priv)
|
||||
int mlx5e_create_flow_tables(struct mlx5e_priv *priv)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -941,16 +872,24 @@ int mlx5e_open_flow_table(struct mlx5e_priv *priv)
|
|||
if (err)
|
||||
goto err_destroy_main_flow_table;
|
||||
|
||||
err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
|
||||
if (err)
|
||||
goto err_destroy_vlan_flow_table;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_vlan_flow_table:
|
||||
mlx5e_destroy_vlan_flow_table(priv);
|
||||
|
||||
err_destroy_main_flow_table:
|
||||
mlx5e_destroy_main_flow_table(priv);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5e_close_flow_table(struct mlx5e_priv *priv)
|
||||
void mlx5e_destroy_flow_tables(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
|
||||
mlx5e_destroy_vlan_flow_table(priv);
|
||||
mlx5e_destroy_main_flow_table(priv);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,47 @@ static void mlx5e_update_carrier_work(struct work_struct *work)
|
|||
mutex_unlock(&priv->state_lock);
|
||||
}
|
||||
|
||||
static void mlx5e_update_pport_counters(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
struct mlx5e_pport_stats *s = &priv->stats.pport;
|
||||
u32 *in;
|
||||
u32 *out;
|
||||
int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
|
||||
|
||||
in = mlx5_vzalloc(sz);
|
||||
out = mlx5_vzalloc(sz);
|
||||
if (!in || !out)
|
||||
goto free_out;
|
||||
|
||||
MLX5_SET(ppcnt_reg, in, local_port, 1);
|
||||
|
||||
MLX5_SET(ppcnt_reg, in, grp, MLX5_IEEE_802_3_COUNTERS_GROUP);
|
||||
mlx5_core_access_reg(mdev, in, sz, out,
|
||||
sz, MLX5_REG_PPCNT, 0, 0);
|
||||
memcpy(s->IEEE_802_3_counters,
|
||||
MLX5_ADDR_OF(ppcnt_reg, out, counter_set),
|
||||
sizeof(s->IEEE_802_3_counters));
|
||||
|
||||
MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2863_COUNTERS_GROUP);
|
||||
mlx5_core_access_reg(mdev, in, sz, out,
|
||||
sz, MLX5_REG_PPCNT, 0, 0);
|
||||
memcpy(s->RFC_2863_counters,
|
||||
MLX5_ADDR_OF(ppcnt_reg, out, counter_set),
|
||||
sizeof(s->RFC_2863_counters));
|
||||
|
||||
MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2819_COUNTERS_GROUP);
|
||||
mlx5_core_access_reg(mdev, in, sz, out,
|
||||
sz, MLX5_REG_PPCNT, 0, 0);
|
||||
memcpy(s->RFC_2819_counters,
|
||||
MLX5_ADDR_OF(ppcnt_reg, out, counter_set),
|
||||
sizeof(s->RFC_2819_counters));
|
||||
|
||||
free_out:
|
||||
kvfree(in);
|
||||
kvfree(out);
|
||||
}
|
||||
|
||||
void mlx5e_update_stats(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
@ -202,6 +243,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
|
|||
s->tx_csum_offload = s->tx_packets - tx_offload_none;
|
||||
s->rx_csum_good = s->rx_packets - s->rx_csum_none;
|
||||
|
||||
mlx5e_update_pport_counters(priv);
|
||||
free_out:
|
||||
kvfree(out);
|
||||
}
|
||||
|
@ -307,6 +349,7 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
|
|||
rq->netdev = c->netdev;
|
||||
rq->channel = c;
|
||||
rq->ix = c->ix;
|
||||
rq->priv = c->priv;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -324,8 +367,7 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
|
|||
|
||||
static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param)
|
||||
{
|
||||
struct mlx5e_channel *c = rq->channel;
|
||||
struct mlx5e_priv *priv = c->priv;
|
||||
struct mlx5e_priv *priv = rq->priv;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
void *in;
|
||||
|
@ -392,11 +434,7 @@ static int mlx5e_modify_rq(struct mlx5e_rq *rq, int curr_state, int next_state)
|
|||
|
||||
static void mlx5e_disable_rq(struct mlx5e_rq *rq)
|
||||
{
|
||||
struct mlx5e_channel *c = rq->channel;
|
||||
struct mlx5e_priv *priv = c->priv;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
mlx5_core_destroy_rq(mdev, rq->rqn);
|
||||
mlx5_core_destroy_rq(rq->priv->mdev, rq->rqn);
|
||||
}
|
||||
|
||||
static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq)
|
||||
|
@ -740,6 +778,7 @@ static int mlx5e_create_cq(struct mlx5e_channel *c,
|
|||
}
|
||||
|
||||
cq->channel = c;
|
||||
cq->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -751,8 +790,7 @@ static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
|
|||
|
||||
static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
|
||||
{
|
||||
struct mlx5e_channel *c = cq->channel;
|
||||
struct mlx5e_priv *priv = c->priv;
|
||||
struct mlx5e_priv *priv = cq->priv;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
struct mlx5_core_cq *mcq = &cq->mcq;
|
||||
|
||||
|
@ -798,8 +836,7 @@ static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
|
|||
|
||||
static void mlx5e_disable_cq(struct mlx5e_cq *cq)
|
||||
{
|
||||
struct mlx5e_channel *c = cq->channel;
|
||||
struct mlx5e_priv *priv = c->priv;
|
||||
struct mlx5e_priv *priv = cq->priv;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
mlx5_core_destroy_cq(mdev, &cq->mcq);
|
||||
|
@ -1119,53 +1156,6 @@ static void mlx5e_close_channels(struct mlx5e_priv *priv)
|
|||
kfree(priv->channel);
|
||||
}
|
||||
|
||||
static int mlx5e_open_tis(struct mlx5e_priv *priv, int tc)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 in[MLX5_ST_SZ_DW(create_tis_in)];
|
||||
void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
|
||||
MLX5_SET(tisc, tisc, prio, tc);
|
||||
MLX5_SET(tisc, tisc, transport_domain, priv->tdn);
|
||||
|
||||
return mlx5_core_create_tis(mdev, in, sizeof(in), &priv->tisn[tc]);
|
||||
}
|
||||
|
||||
static void mlx5e_close_tis(struct mlx5e_priv *priv, int tc)
|
||||
{
|
||||
mlx5_core_destroy_tis(priv->mdev, priv->tisn[tc]);
|
||||
}
|
||||
|
||||
static int mlx5e_open_tises(struct mlx5e_priv *priv)
|
||||
{
|
||||
int err;
|
||||
int tc;
|
||||
|
||||
for (tc = 0; tc < priv->params.num_tc; tc++) {
|
||||
err = mlx5e_open_tis(priv, tc);
|
||||
if (err)
|
||||
goto err_close_tises;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_close_tises:
|
||||
for (tc--; tc >= 0; tc--)
|
||||
mlx5e_close_tis(priv, tc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_close_tises(struct mlx5e_priv *priv)
|
||||
{
|
||||
int tc;
|
||||
|
||||
for (tc = 0; tc < priv->params.num_tc; tc++)
|
||||
mlx5e_close_tis(priv, tc);
|
||||
}
|
||||
|
||||
static int mlx5e_rx_hash_fn(int hfunc)
|
||||
{
|
||||
return (hfunc == ETH_RSS_HASH_TOP) ?
|
||||
|
@ -1184,16 +1174,53 @@ static int mlx5e_bits_invert(unsigned long a, int size)
|
|||
return inv;
|
||||
}
|
||||
|
||||
static int mlx5e_open_rqt(struct mlx5e_priv *priv)
|
||||
static void mlx5e_fill_rqt_rqns(struct mlx5e_priv *priv, void *rqtc,
|
||||
enum mlx5e_rqt_ix rqt_ix)
|
||||
{
|
||||
int i;
|
||||
int log_sz;
|
||||
|
||||
switch (rqt_ix) {
|
||||
case MLX5E_INDIRECTION_RQT:
|
||||
log_sz = priv->params.rx_hash_log_tbl_sz;
|
||||
for (i = 0; i < (1 << log_sz); i++) {
|
||||
int ix = i;
|
||||
|
||||
if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR)
|
||||
ix = mlx5e_bits_invert(i, log_sz);
|
||||
|
||||
ix = ix % priv->params.num_channels;
|
||||
MLX5_SET(rqtc, rqtc, rq_num[i],
|
||||
test_bit(MLX5E_STATE_OPENED, &priv->state) ?
|
||||
priv->channel[ix]->rq.rqn :
|
||||
priv->drop_rq.rqn);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default: /* MLX5E_SINGLE_RQ_RQT */
|
||||
MLX5_SET(rqtc, rqtc, rq_num[0],
|
||||
test_bit(MLX5E_STATE_OPENED, &priv->state) ?
|
||||
priv->channel[0]->rq.rqn :
|
||||
priv->drop_rq.rqn);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx5e_create_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 *in;
|
||||
void *rqtc;
|
||||
int inlen;
|
||||
int log_sz;
|
||||
int sz;
|
||||
int err;
|
||||
int log_tbl_sz = priv->params.rx_hash_log_tbl_sz;
|
||||
int sz = 1 << log_tbl_sz;
|
||||
int i;
|
||||
|
||||
log_sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 0 :
|
||||
priv->params.rx_hash_log_tbl_sz;
|
||||
sz = 1 << log_sz;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
|
||||
in = mlx5_vzalloc(inlen);
|
||||
|
@ -1205,26 +1232,343 @@ static int mlx5e_open_rqt(struct mlx5e_priv *priv)
|
|||
MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
|
||||
MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
int ix = i;
|
||||
mlx5e_fill_rqt_rqns(priv, rqtc, rqt_ix);
|
||||
|
||||
if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR)
|
||||
ix = mlx5e_bits_invert(i, log_tbl_sz);
|
||||
|
||||
ix = ix % priv->params.num_channels;
|
||||
MLX5_SET(rqtc, rqtc, rq_num[i], priv->channel[ix]->rq.rqn);
|
||||
}
|
||||
|
||||
err = mlx5_core_create_rqt(mdev, in, inlen, &priv->rqtn);
|
||||
err = mlx5_core_create_rqt(mdev, in, inlen, &priv->rqtn[rqt_ix]);
|
||||
|
||||
kvfree(in);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_close_rqt(struct mlx5e_priv *priv)
|
||||
static int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
{
|
||||
mlx5_core_destroy_rqt(priv->mdev, priv->rqtn);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 *in;
|
||||
void *rqtc;
|
||||
int inlen;
|
||||
int log_sz;
|
||||
int sz;
|
||||
int err;
|
||||
|
||||
log_sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 0 :
|
||||
priv->params.rx_hash_log_tbl_sz;
|
||||
sz = 1 << log_sz;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * sz;
|
||||
in = mlx5_vzalloc(inlen);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
rqtc = MLX5_ADDR_OF(modify_rqt_in, in, ctx);
|
||||
|
||||
MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
|
||||
|
||||
mlx5e_fill_rqt_rqns(priv, rqtc, rqt_ix);
|
||||
|
||||
MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1);
|
||||
|
||||
err = mlx5_core_modify_rqt(mdev, priv->rqtn[rqt_ix], in, inlen);
|
||||
|
||||
kvfree(in);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_destroy_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
{
|
||||
mlx5_core_destroy_rqt(priv->mdev, priv->rqtn[rqt_ix]);
|
||||
}
|
||||
|
||||
static void mlx5e_redirect_rqts(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT);
|
||||
mlx5e_redirect_rqt(priv, MLX5E_SINGLE_RQ_RQT);
|
||||
}
|
||||
|
||||
static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
|
||||
{
|
||||
if (!priv->params.lro_en)
|
||||
return;
|
||||
|
||||
#define ROUGH_MAX_L2_L3_HDR_SZ 256
|
||||
|
||||
MLX5_SET(tirc, tirc, lro_enable_mask,
|
||||
MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO |
|
||||
MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO);
|
||||
MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
|
||||
(priv->params.lro_wqe_sz -
|
||||
ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
|
||||
MLX5_SET(tirc, tirc, lro_timeout_period_usecs,
|
||||
MLX5_CAP_ETH(priv->mdev,
|
||||
lro_timer_supported_periods[3]));
|
||||
}
|
||||
|
||||
static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
void *in;
|
||||
void *tirc;
|
||||
int inlen;
|
||||
int err;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
|
||||
in = mlx5_vzalloc(inlen);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
MLX5_SET(modify_tir_in, in, bitmask.lro, 1);
|
||||
tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
|
||||
|
||||
mlx5e_build_tir_ctx_lro(tirc, priv);
|
||||
|
||||
err = mlx5_core_modify_tir(mdev, priv->tirn[tt], in, inlen);
|
||||
|
||||
kvfree(in);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_set_dev_port_mtu(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int hw_mtu;
|
||||
int err;
|
||||
|
||||
err = mlx5_set_port_mtu(mdev, MLX5E_SW2HW_MTU(netdev->mtu), 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlx5_query_port_oper_mtu(mdev, &hw_mtu, 1);
|
||||
|
||||
if (MLX5E_HW2SW_MTU(hw_mtu) != netdev->mtu)
|
||||
netdev_warn(netdev, "%s: Port MTU %d is different than netdev mtu %d\n",
|
||||
__func__, MLX5E_HW2SW_MTU(hw_mtu), netdev->mtu);
|
||||
|
||||
netdev->mtu = MLX5E_HW2SW_MTU(hw_mtu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5e_open_locked(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int num_txqs;
|
||||
int err;
|
||||
|
||||
set_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
|
||||
num_txqs = priv->params.num_channels * priv->params.num_tc;
|
||||
netif_set_real_num_tx_queues(netdev, num_txqs);
|
||||
netif_set_real_num_rx_queues(netdev, priv->params.num_channels);
|
||||
|
||||
err = mlx5e_set_dev_port_mtu(netdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mlx5e_open_channels(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_open_channels failed, %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
mlx5e_update_carrier(priv);
|
||||
mlx5e_redirect_rqts(priv);
|
||||
|
||||
schedule_delayed_work(&priv->update_stats_work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_open(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
err = mlx5e_open_locked(netdev);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_close_locked(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
clear_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
|
||||
mlx5e_redirect_rqts(priv);
|
||||
netif_carrier_off(priv->netdev);
|
||||
mlx5e_close_channels(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_close(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
err = mlx5e_close_locked(netdev);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_create_drop_rq(struct mlx5e_priv *priv,
|
||||
struct mlx5e_rq *rq,
|
||||
struct mlx5e_rq_param *param)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
void *rqc = param->rqc;
|
||||
void *rqc_wq = MLX5_ADDR_OF(rqc, rqc, wq);
|
||||
int err;
|
||||
|
||||
param->wq.db_numa_node = param->wq.buf_numa_node;
|
||||
|
||||
err = mlx5_wq_ll_create(mdev, ¶m->wq, rqc_wq, &rq->wq,
|
||||
&rq->wq_ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rq->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_create_drop_cq(struct mlx5e_priv *priv,
|
||||
struct mlx5e_cq *cq,
|
||||
struct mlx5e_cq_param *param)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
struct mlx5_core_cq *mcq = &cq->mcq;
|
||||
int eqn_not_used;
|
||||
int irqn;
|
||||
int err;
|
||||
|
||||
err = mlx5_cqwq_create(mdev, ¶m->wq, param->cqc, &cq->wq,
|
||||
&cq->wq_ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
|
||||
|
||||
mcq->cqe_sz = 64;
|
||||
mcq->set_ci_db = cq->wq_ctrl.db.db;
|
||||
mcq->arm_db = cq->wq_ctrl.db.db + 1;
|
||||
*mcq->set_ci_db = 0;
|
||||
*mcq->arm_db = 0;
|
||||
mcq->vector = param->eq_ix;
|
||||
mcq->comp = mlx5e_completion_event;
|
||||
mcq->event = mlx5e_cq_error_event;
|
||||
mcq->irqn = irqn;
|
||||
mcq->uar = &priv->cq_uar;
|
||||
|
||||
cq->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_open_drop_rq(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_cq_param cq_param;
|
||||
struct mlx5e_rq_param rq_param;
|
||||
struct mlx5e_rq *rq = &priv->drop_rq;
|
||||
struct mlx5e_cq *cq = &priv->drop_rq.cq;
|
||||
int err;
|
||||
|
||||
memset(&cq_param, 0, sizeof(cq_param));
|
||||
memset(&rq_param, 0, sizeof(rq_param));
|
||||
mlx5e_build_rx_cq_param(priv, &cq_param);
|
||||
mlx5e_build_rq_param(priv, &rq_param);
|
||||
|
||||
err = mlx5e_create_drop_cq(priv, cq, &cq_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mlx5e_enable_cq(cq, &cq_param);
|
||||
if (err)
|
||||
goto err_destroy_cq;
|
||||
|
||||
err = mlx5e_create_drop_rq(priv, rq, &rq_param);
|
||||
if (err)
|
||||
goto err_disable_cq;
|
||||
|
||||
err = mlx5e_enable_rq(rq, &rq_param);
|
||||
if (err)
|
||||
goto err_destroy_rq;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_rq:
|
||||
mlx5e_destroy_rq(&priv->drop_rq);
|
||||
|
||||
err_disable_cq:
|
||||
mlx5e_disable_cq(&priv->drop_rq.cq);
|
||||
|
||||
err_destroy_cq:
|
||||
mlx5e_destroy_cq(&priv->drop_rq.cq);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_close_drop_rq(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_disable_rq(&priv->drop_rq);
|
||||
mlx5e_destroy_rq(&priv->drop_rq);
|
||||
mlx5e_disable_cq(&priv->drop_rq.cq);
|
||||
mlx5e_destroy_cq(&priv->drop_rq.cq);
|
||||
}
|
||||
|
||||
static int mlx5e_create_tis(struct mlx5e_priv *priv, int tc)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 in[MLX5_ST_SZ_DW(create_tis_in)];
|
||||
void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
|
||||
MLX5_SET(tisc, tisc, prio, tc);
|
||||
MLX5_SET(tisc, tisc, transport_domain, priv->tdn);
|
||||
|
||||
return mlx5_core_create_tis(mdev, in, sizeof(in), &priv->tisn[tc]);
|
||||
}
|
||||
|
||||
static void mlx5e_destroy_tis(struct mlx5e_priv *priv, int tc)
|
||||
{
|
||||
mlx5_core_destroy_tis(priv->mdev, priv->tisn[tc]);
|
||||
}
|
||||
|
||||
static int mlx5e_create_tises(struct mlx5e_priv *priv)
|
||||
{
|
||||
int err;
|
||||
int tc;
|
||||
|
||||
for (tc = 0; tc < priv->params.num_tc; tc++) {
|
||||
err = mlx5e_create_tis(priv, tc);
|
||||
if (err)
|
||||
goto err_close_tises;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_close_tises:
|
||||
for (tc--; tc >= 0; tc--)
|
||||
mlx5e_destroy_tis(priv, tc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_destroy_tises(struct mlx5e_priv *priv)
|
||||
{
|
||||
int tc;
|
||||
|
||||
for (tc = 0; tc < priv->params.num_tc; tc++)
|
||||
mlx5e_destroy_tis(priv, tc);
|
||||
}
|
||||
|
||||
static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
|
||||
|
@ -1233,8 +1577,6 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
|
|||
|
||||
MLX5_SET(tirc, tirc, transport_domain, priv->tdn);
|
||||
|
||||
#define ROUGH_MAX_L2_L3_HDR_SZ 256
|
||||
|
||||
#define MLX5_HASH_IP (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP)
|
||||
|
||||
|
@ -1247,30 +1589,19 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
|
|||
MLX5_HASH_FIELD_SEL_DST_IP |\
|
||||
MLX5_HASH_FIELD_SEL_IPSEC_SPI)
|
||||
|
||||
if (priv->params.lro_en) {
|
||||
MLX5_SET(tirc, tirc, lro_enable_mask,
|
||||
MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO |
|
||||
MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO);
|
||||
MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
|
||||
(priv->params.lro_wqe_sz -
|
||||
ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
|
||||
MLX5_SET(tirc, tirc, lro_timeout_period_usecs,
|
||||
MLX5_CAP_ETH(priv->mdev,
|
||||
lro_timer_supported_periods[3]));
|
||||
}
|
||||
mlx5e_build_tir_ctx_lro(tirc, priv);
|
||||
|
||||
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
|
||||
|
||||
switch (tt) {
|
||||
case MLX5E_TT_ANY:
|
||||
MLX5_SET(tirc, tirc, disp_type,
|
||||
MLX5_TIRC_DISP_TYPE_DIRECT);
|
||||
MLX5_SET(tirc, tirc, inline_rqn,
|
||||
priv->channel[0]->rq.rqn);
|
||||
MLX5_SET(tirc, tirc, indirect_table,
|
||||
priv->rqtn[MLX5E_SINGLE_RQ_RQT]);
|
||||
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
|
||||
break;
|
||||
default:
|
||||
MLX5_SET(tirc, tirc, disp_type,
|
||||
MLX5_TIRC_DISP_TYPE_INDIRECT);
|
||||
MLX5_SET(tirc, tirc, indirect_table,
|
||||
priv->rqtn);
|
||||
priv->rqtn[MLX5E_INDIRECTION_RQT]);
|
||||
MLX5_SET(tirc, tirc, rx_hash_fn,
|
||||
mlx5e_rx_hash_fn(priv->params.rss_hfunc));
|
||||
if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
|
||||
|
@ -1366,7 +1697,7 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
|
|||
}
|
||||
}
|
||||
|
||||
static int mlx5e_open_tir(struct mlx5e_priv *priv, int tt)
|
||||
static int mlx5e_create_tir(struct mlx5e_priv *priv, int tt)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 *in;
|
||||
|
@ -1390,184 +1721,37 @@ static int mlx5e_open_tir(struct mlx5e_priv *priv, int tt)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_close_tir(struct mlx5e_priv *priv, int tt)
|
||||
static void mlx5e_destroy_tir(struct mlx5e_priv *priv, int tt)
|
||||
{
|
||||
mlx5_core_destroy_tir(priv->mdev, priv->tirn[tt]);
|
||||
}
|
||||
|
||||
static int mlx5e_open_tirs(struct mlx5e_priv *priv)
|
||||
static int mlx5e_create_tirs(struct mlx5e_priv *priv)
|
||||
{
|
||||
int err;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MLX5E_NUM_TT; i++) {
|
||||
err = mlx5e_open_tir(priv, i);
|
||||
err = mlx5e_create_tir(priv, i);
|
||||
if (err)
|
||||
goto err_close_tirs;
|
||||
goto err_destroy_tirs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_close_tirs:
|
||||
err_destroy_tirs:
|
||||
for (i--; i >= 0; i--)
|
||||
mlx5e_close_tir(priv, i);
|
||||
mlx5e_destroy_tir(priv, i);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_close_tirs(struct mlx5e_priv *priv)
|
||||
static void mlx5e_destroy_tirs(struct mlx5e_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MLX5E_NUM_TT; i++)
|
||||
mlx5e_close_tir(priv, i);
|
||||
}
|
||||
|
||||
static int mlx5e_set_dev_port_mtu(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int hw_mtu;
|
||||
int err;
|
||||
|
||||
err = mlx5_set_port_mtu(mdev, MLX5E_SW2HW_MTU(netdev->mtu), 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlx5_query_port_oper_mtu(mdev, &hw_mtu, 1);
|
||||
|
||||
if (MLX5E_HW2SW_MTU(hw_mtu) != netdev->mtu)
|
||||
netdev_warn(netdev, "%s: Port MTU %d is different than netdev mtu %d\n",
|
||||
__func__, MLX5E_HW2SW_MTU(hw_mtu), netdev->mtu);
|
||||
|
||||
netdev->mtu = MLX5E_HW2SW_MTU(hw_mtu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5e_open_locked(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int num_txqs;
|
||||
int err;
|
||||
|
||||
num_txqs = priv->params.num_channels * priv->params.num_tc;
|
||||
netif_set_real_num_tx_queues(netdev, num_txqs);
|
||||
netif_set_real_num_rx_queues(netdev, priv->params.num_channels);
|
||||
|
||||
err = mlx5e_set_dev_port_mtu(netdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mlx5e_open_tises(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_open_tises failed, %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mlx5e_open_channels(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_open_channels failed, %d\n",
|
||||
__func__, err);
|
||||
goto err_close_tises;
|
||||
}
|
||||
|
||||
err = mlx5e_open_rqt(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_open_rqt failed, %d\n",
|
||||
__func__, err);
|
||||
goto err_close_channels;
|
||||
}
|
||||
|
||||
err = mlx5e_open_tirs(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_open_tir failed, %d\n",
|
||||
__func__, err);
|
||||
goto err_close_rqls;
|
||||
}
|
||||
|
||||
err = mlx5e_open_flow_table(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_open_flow_table failed, %d\n",
|
||||
__func__, err);
|
||||
goto err_close_tirs;
|
||||
}
|
||||
|
||||
err = mlx5e_add_all_vlan_rules(priv);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5e_add_all_vlan_rules failed, %d\n",
|
||||
__func__, err);
|
||||
goto err_close_flow_table;
|
||||
}
|
||||
|
||||
mlx5e_init_eth_addr(priv);
|
||||
|
||||
set_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
|
||||
mlx5e_update_carrier(priv);
|
||||
mlx5e_set_rx_mode_core(priv);
|
||||
|
||||
schedule_delayed_work(&priv->update_stats_work, 0);
|
||||
return 0;
|
||||
|
||||
err_close_flow_table:
|
||||
mlx5e_close_flow_table(priv);
|
||||
|
||||
err_close_tirs:
|
||||
mlx5e_close_tirs(priv);
|
||||
|
||||
err_close_rqls:
|
||||
mlx5e_close_rqt(priv);
|
||||
|
||||
err_close_channels:
|
||||
mlx5e_close_channels(priv);
|
||||
|
||||
err_close_tises:
|
||||
mlx5e_close_tises(priv);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_open(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
err = mlx5e_open_locked(netdev);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_close_locked(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
clear_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
|
||||
mlx5e_set_rx_mode_core(priv);
|
||||
mlx5e_del_all_vlan_rules(priv);
|
||||
netif_carrier_off(priv->netdev);
|
||||
mlx5e_close_flow_table(priv);
|
||||
mlx5e_close_tirs(priv);
|
||||
mlx5e_close_rqt(priv);
|
||||
mlx5e_close_channels(priv);
|
||||
mlx5e_close_tises(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_close(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
err = mlx5e_close_locked(netdev);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
mlx5e_destroy_tir(priv, i);
|
||||
}
|
||||
|
||||
static struct rtnl_link_stats64 *
|
||||
|
@ -1631,11 +1815,15 @@ static int mlx5e_set_features(struct net_device *netdev,
|
|||
mlx5e_close_locked(priv->netdev);
|
||||
|
||||
priv->params.lro_en = !!(features & NETIF_F_LRO);
|
||||
mlx5e_modify_tir_lro(priv, MLX5E_TT_IPV4_TCP);
|
||||
mlx5e_modify_tir_lro(priv, MLX5E_TT_IPV6_TCP);
|
||||
|
||||
if (was_opened)
|
||||
err = mlx5e_open_locked(priv->netdev);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
if (changes & NETIF_F_HW_VLAN_CTAG_FILTER) {
|
||||
if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
|
||||
mlx5e_enable_vlan_filter(priv);
|
||||
|
@ -1643,8 +1831,6 @@ static int mlx5e_set_features(struct net_device *netdev,
|
|||
mlx5e_disable_vlan_filter(priv);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1891,16 +2077,73 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
|
|||
goto err_dealloc_transport_domain;
|
||||
}
|
||||
|
||||
err = register_netdev(netdev);
|
||||
err = mlx5e_create_tises(priv);
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
|
||||
mlx5_core_warn(mdev, "create tises failed, %d\n", err);
|
||||
goto err_destroy_mkey;
|
||||
}
|
||||
|
||||
err = mlx5e_open_drop_rq(priv);
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
|
||||
goto err_destroy_tises;
|
||||
}
|
||||
|
||||
err = mlx5e_create_rqt(priv, MLX5E_INDIRECTION_RQT);
|
||||
if (err) {
|
||||
mlx5_core_warn(mdev, "create rqt(INDIR) failed, %d\n", err);
|
||||
goto err_close_drop_rq;
|
||||
}
|
||||
|
||||
err = mlx5e_create_rqt(priv, MLX5E_SINGLE_RQ_RQT);
|
||||
if (err) {
|
||||
mlx5_core_warn(mdev, "create rqt(SINGLE) failed, %d\n", err);
|
||||
goto err_destroy_rqt_indir;
|
||||
}
|
||||
|
||||
err = mlx5e_create_tirs(priv);
|
||||
if (err) {
|
||||
mlx5_core_warn(mdev, "create tirs failed, %d\n", err);
|
||||
goto err_destroy_rqt_single;
|
||||
}
|
||||
|
||||
err = mlx5e_create_flow_tables(priv);
|
||||
if (err) {
|
||||
mlx5_core_warn(mdev, "create flow tables failed, %d\n", err);
|
||||
goto err_destroy_tirs;
|
||||
}
|
||||
|
||||
mlx5e_init_eth_addr(priv);
|
||||
|
||||
err = register_netdev(netdev);
|
||||
if (err) {
|
||||
mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
|
||||
goto err_destroy_flow_tables;
|
||||
}
|
||||
|
||||
mlx5e_enable_async_events(priv);
|
||||
schedule_work(&priv->set_rx_mode_work);
|
||||
|
||||
return priv;
|
||||
|
||||
err_destroy_flow_tables:
|
||||
mlx5e_destroy_flow_tables(priv);
|
||||
|
||||
err_destroy_tirs:
|
||||
mlx5e_destroy_tirs(priv);
|
||||
|
||||
err_destroy_rqt_single:
|
||||
mlx5e_destroy_rqt(priv, MLX5E_SINGLE_RQ_RQT);
|
||||
|
||||
err_destroy_rqt_indir:
|
||||
mlx5e_destroy_rqt(priv, MLX5E_INDIRECTION_RQT);
|
||||
|
||||
err_close_drop_rq:
|
||||
mlx5e_close_drop_rq(priv);
|
||||
|
||||
err_destroy_tises:
|
||||
mlx5e_destroy_tises(priv);
|
||||
|
||||
err_destroy_mkey:
|
||||
mlx5_core_destroy_mkey(mdev, &priv->mr);
|
||||
|
||||
|
@ -1924,13 +2167,22 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
|
|||
struct mlx5e_priv *priv = vpriv;
|
||||
struct net_device *netdev = priv->netdev;
|
||||
|
||||
set_bit(MLX5E_STATE_DESTROYING, &priv->state);
|
||||
|
||||
schedule_work(&priv->set_rx_mode_work);
|
||||
mlx5e_disable_async_events(priv);
|
||||
flush_scheduled_work();
|
||||
unregister_netdev(netdev);
|
||||
mlx5e_destroy_flow_tables(priv);
|
||||
mlx5e_destroy_tirs(priv);
|
||||
mlx5e_destroy_rqt(priv, MLX5E_SINGLE_RQ_RQT);
|
||||
mlx5e_destroy_rqt(priv, MLX5E_INDIRECTION_RQT);
|
||||
mlx5e_close_drop_rq(priv);
|
||||
mlx5e_destroy_tises(priv);
|
||||
mlx5_core_destroy_mkey(priv->mdev, &priv->mr);
|
||||
mlx5_dealloc_transport_domain(priv->mdev, priv->tdn);
|
||||
mlx5_core_dealloc_pd(priv->mdev, priv->pdn);
|
||||
mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar);
|
||||
mlx5e_disable_async_events(priv);
|
||||
flush_scheduled_work();
|
||||
free_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -163,6 +163,18 @@ int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, int inlen,
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5_core_modify_tir(struct mlx5_core_dev *dev, u32 tirn, u32 *in,
|
||||
int inlen)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(modify_tir_out)];
|
||||
|
||||
MLX5_SET(modify_tir_in, in, tirn, tirn);
|
||||
MLX5_SET(modify_tir_in, in, opcode, MLX5_CMD_OP_MODIFY_TIR);
|
||||
|
||||
memset(out, 0, sizeof(out));
|
||||
return mlx5_cmd_exec_check_status(dev, in, inlen, out, sizeof(out));
|
||||
}
|
||||
|
||||
void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(destroy_tir_out)];
|
||||
|
@ -375,6 +387,18 @@ int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen,
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5_core_modify_rqt(struct mlx5_core_dev *dev, u32 rqtn, u32 *in,
|
||||
int inlen)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(modify_rqt_out)];
|
||||
|
||||
MLX5_SET(modify_rqt_in, in, rqtn, rqtn);
|
||||
MLX5_SET(modify_rqt_in, in, opcode, MLX5_CMD_OP_MODIFY_RQT);
|
||||
|
||||
memset(out, 0, sizeof(out));
|
||||
return mlx5_cmd_exec_check_status(dev, in, inlen, out, sizeof(out));
|
||||
}
|
||||
|
||||
void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(destroy_rqt_in)];
|
||||
|
|
|
@ -45,6 +45,8 @@ int mlx5_core_modify_sq(struct mlx5_core_dev *dev, u32 sqn, u32 *in, int inlen);
|
|||
void mlx5_core_destroy_sq(struct mlx5_core_dev *dev, u32 sqn);
|
||||
int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, int inlen,
|
||||
u32 *tirn);
|
||||
int mlx5_core_modify_tir(struct mlx5_core_dev *dev, u32 tirn, u32 *in,
|
||||
int inlen);
|
||||
void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn);
|
||||
int mlx5_core_create_tis(struct mlx5_core_dev *dev, u32 *in, int inlen,
|
||||
u32 *tisn);
|
||||
|
@ -63,6 +65,8 @@ int mlx5_core_arm_xsrq(struct mlx5_core_dev *dev, u32 rmpn, u16 lwm);
|
|||
|
||||
int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen,
|
||||
u32 *rqtn);
|
||||
int mlx5_core_modify_rqt(struct mlx5_core_dev *dev, u32 rqtn, u32 *in,
|
||||
int inlen);
|
||||
void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn);
|
||||
|
||||
#endif /* __TRANSOBJ_H__ */
|
||||
|
|
|
@ -1182,6 +1182,16 @@ enum {
|
|||
MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR = 0x40,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_IEEE_802_3_COUNTERS_GROUP = 0x0,
|
||||
MLX5_RFC_2863_COUNTERS_GROUP = 0x1,
|
||||
MLX5_RFC_2819_COUNTERS_GROUP = 0x2,
|
||||
MLX5_RFC_3635_COUNTERS_GROUP = 0x3,
|
||||
MLX5_ETHERNET_EXTENDED_COUNTERS_GROUP = 0x5,
|
||||
MLX5_PER_PRIORITY_COUNTERS_GROUP = 0x10,
|
||||
MLX5_PER_TRAFFIC_CLASS_COUNTERS_GROUP = 0x11
|
||||
};
|
||||
|
||||
static inline u16 mlx5_to_sw_pkey_sz(int pkey_sz)
|
||||
{
|
||||
if (pkey_sz > MLX5_MAX_LOG_PKEY_TABLE)
|
||||
|
|
|
@ -103,6 +103,7 @@ enum {
|
|||
MLX5_REG_PMTU = 0x5003,
|
||||
MLX5_REG_PTYS = 0x5004,
|
||||
MLX5_REG_PAOS = 0x5006,
|
||||
MLX5_REG_PPCNT = 0x5008,
|
||||
MLX5_REG_PMAOS = 0x5012,
|
||||
MLX5_REG_PUDE = 0x5009,
|
||||
MLX5_REG_PMPE = 0x5010,
|
||||
|
|
|
@ -4050,6 +4050,13 @@ struct mlx5_ifc_modify_tis_in_bits {
|
|||
struct mlx5_ifc_tisc_bits ctx;
|
||||
};
|
||||
|
||||
struct mlx5_ifc_modify_tir_bitmask_bits {
|
||||
u8 reserved[0x20];
|
||||
|
||||
u8 reserved1[0x1f];
|
||||
u8 lro[0x1];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_modify_tir_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_0[0x18];
|
||||
|
@ -4071,7 +4078,7 @@ struct mlx5_ifc_modify_tir_in_bits {
|
|||
|
||||
u8 reserved_3[0x20];
|
||||
|
||||
u8 modify_bitmask[0x40];
|
||||
struct mlx5_ifc_modify_tir_bitmask_bits bitmask;
|
||||
|
||||
u8 reserved_4[0x40];
|
||||
|
||||
|
@ -4116,6 +4123,13 @@ struct mlx5_ifc_modify_rqt_out_bits {
|
|||
u8 reserved_1[0x40];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_rqt_bitmask_bits {
|
||||
u8 reserved[0x20];
|
||||
|
||||
u8 reserved1[0x1f];
|
||||
u8 rqn_list[0x1];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_modify_rqt_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_0[0x10];
|
||||
|
@ -4128,7 +4142,7 @@ struct mlx5_ifc_modify_rqt_in_bits {
|
|||
|
||||
u8 reserved_3[0x20];
|
||||
|
||||
u8 modify_bitmask[0x40];
|
||||
struct mlx5_ifc_rqt_bitmask_bits bitmask;
|
||||
|
||||
u8 reserved_4[0x40];
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче