Commit c71b5ad0 authored by David S. Miller's avatar David S. Miller

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 ba7591d8 ("ebpf: add skb->hash to
offset map for usage in {cls, act}_bpf or filters")
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents adc4cc99 efea389d
...@@ -138,6 +138,80 @@ struct mlx5e_vport_stats { ...@@ -138,6 +138,80 @@ struct mlx5e_vport_stats {
#define NUM_VPORT_COUNTERS 31 #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] = { static const char rq_stats_strings[][ETH_GSTRING_LEN] = {
"packets", "packets",
"csum_none", "csum_none",
...@@ -180,6 +254,7 @@ struct mlx5e_sq_stats { ...@@ -180,6 +254,7 @@ struct mlx5e_sq_stats {
struct mlx5e_stats { struct mlx5e_stats {
struct mlx5e_vport_stats vport; struct mlx5e_vport_stats vport;
struct mlx5e_pport_stats pport;
}; };
struct mlx5e_params { struct mlx5e_params {
...@@ -217,6 +292,7 @@ struct mlx5e_cq { ...@@ -217,6 +292,7 @@ struct mlx5e_cq {
struct napi_struct *napi; struct napi_struct *napi;
struct mlx5_core_cq mcq; struct mlx5_core_cq mcq;
struct mlx5e_channel *channel; struct mlx5e_channel *channel;
struct mlx5e_priv *priv;
/* control */ /* control */
struct mlx5_wq_ctrl wq_ctrl; struct mlx5_wq_ctrl wq_ctrl;
...@@ -240,6 +316,7 @@ struct mlx5e_rq { ...@@ -240,6 +316,7 @@ struct mlx5e_rq {
struct mlx5_wq_ctrl wq_ctrl; struct mlx5_wq_ctrl wq_ctrl;
u32 rqn; u32 rqn;
struct mlx5e_channel *channel; struct mlx5e_channel *channel;
struct mlx5e_priv *priv;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
struct mlx5e_tx_skb_cb { struct mlx5e_tx_skb_cb {
...@@ -344,10 +421,10 @@ enum mlx5e_traffic_types { ...@@ -344,10 +421,10 @@ enum mlx5e_traffic_types {
MLX5E_NUM_TT, MLX5E_NUM_TT,
}; };
enum { enum mlx5e_rqt_ix {
MLX5E_RQT_SPREADING = 0, MLX5E_INDIRECTION_RQT,
MLX5E_RQT_DEFAULT_RQ = 1, MLX5E_SINGLE_RQ_RQT,
MLX5E_NUM_RQT = 2, MLX5E_NUM_RQT,
}; };
struct mlx5e_eth_addr_info { struct mlx5e_eth_addr_info {
...@@ -372,10 +449,10 @@ struct mlx5e_eth_addr_db { ...@@ -372,10 +449,10 @@ struct mlx5e_eth_addr_db {
enum { enum {
MLX5E_STATE_ASYNC_EVENTS_ENABLE, MLX5E_STATE_ASYNC_EVENTS_ENABLE,
MLX5E_STATE_OPENED, MLX5E_STATE_OPENED,
MLX5E_STATE_DESTROYING,
}; };
struct mlx5e_vlan_db { struct mlx5e_vlan_db {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u32 active_vlans_ft_ix[VLAN_N_VID]; u32 active_vlans_ft_ix[VLAN_N_VID];
u32 untagged_rule_ft_ix; u32 untagged_rule_ft_ix;
u32 any_vlan_rule_ft_ix; u32 any_vlan_rule_ft_ix;
...@@ -399,10 +476,11 @@ struct mlx5e_priv { ...@@ -399,10 +476,11 @@ struct mlx5e_priv {
u32 pdn; u32 pdn;
u32 tdn; u32 tdn;
struct mlx5_core_mr mr; struct mlx5_core_mr mr;
struct mlx5e_rq drop_rq;
struct mlx5e_channel **channel; struct mlx5e_channel **channel;
u32 tisn[MLX5E_MAX_NUM_TC]; u32 tisn[MLX5E_MAX_NUM_TC];
u32 rqtn; u32 rqtn[MLX5E_NUM_RQT];
u32 tirn[MLX5E_NUM_TT]; u32 tirn[MLX5E_NUM_TT];
struct mlx5e_flow_table ft; struct mlx5e_flow_table ft;
...@@ -479,10 +557,9 @@ struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq); ...@@ -479,10 +557,9 @@ struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq);
void mlx5e_update_stats(struct mlx5e_priv *priv); void mlx5e_update_stats(struct mlx5e_priv *priv);
int mlx5e_open_flow_table(struct mlx5e_priv *priv); int mlx5e_create_flow_tables(struct mlx5e_priv *priv);
void mlx5e_close_flow_table(struct mlx5e_priv *priv); void mlx5e_destroy_flow_tables(struct mlx5e_priv *priv);
void mlx5e_init_eth_addr(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); void mlx5e_set_rx_mode_work(struct work_struct *work);
int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto, 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, ...@@ -491,8 +568,6 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
u16 vid); u16 vid);
void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv); void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv);
void mlx5e_disable_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_open_locked(struct net_device *netdev);
int mlx5e_close_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) ...@@ -171,7 +171,7 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset)
switch (sset) { switch (sset) {
case ETH_SS_STATS: 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 * NUM_RQ_STATS +
priv->params.num_channels * priv->params.num_tc * priv->params.num_channels * priv->params.num_tc *
NUM_SQ_STATS; NUM_SQ_STATS;
...@@ -200,6 +200,11 @@ static void mlx5e_get_strings(struct net_device *dev, ...@@ -200,6 +200,11 @@ static void mlx5e_get_strings(struct net_device *dev,
strcpy(data + (idx++) * ETH_GSTRING_LEN, strcpy(data + (idx++) * ETH_GSTRING_LEN,
vport_strings[i]); 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 */ /* per channel counters */
for (i = 0; i < priv->params.num_channels; i++) for (i = 0; i < priv->params.num_channels; i++)
for (j = 0; j < NUM_RQ_STATS; j++) for (j = 0; j < NUM_RQ_STATS; j++)
...@@ -234,6 +239,9 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev, ...@@ -234,6 +239,9 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
for (i = 0; i < NUM_VPORT_COUNTERS; i++) for (i = 0; i < NUM_VPORT_COUNTERS; i++)
data[idx++] = ((u64 *)&priv->stats.vport)[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 */ /* per channel counters */
for (i = 0; i < priv->params.num_channels; i++) for (i = 0; i < priv->params.num_channels; i++)
for (j = 0; j < NUM_RQ_STATS; j++) for (j = 0; j < NUM_RQ_STATS; j++)
......
...@@ -594,44 +594,28 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv, ...@@ -594,44 +594,28 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
void mlx5e_enable_vlan_filter(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;
priv->vlan.filter_disabled = false; mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
0);
}
} }
void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv) 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;
priv->vlan.filter_disabled = true; mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
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, int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
u16 vid) u16 vid)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); 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 mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
return err;
} }
int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto, 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, ...@@ -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); struct mlx5e_priv *priv = netdev_priv(dev);
mutex_lock(&priv->state_lock); mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
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);
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; 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) \ #define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
for (i = 0; i < MLX5E_ETH_ADDR_HASH_SIZE; i++) \ for (i = 0; i < MLX5E_ETH_ADDR_HASH_SIZE; i++) \
hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist) hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
...@@ -752,18 +691,21 @@ static void mlx5e_handle_netdev_addr(struct mlx5e_priv *priv) ...@@ -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) mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.netdev_mc, i)
hn->action = MLX5E_ACTION_DEL; 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_sync_netdev_addr(priv);
mlx5e_apply_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 mlx5e_eth_addr_db *ea = &priv->eth_addr;
struct net_device *ndev = priv->netdev; 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 promisc_enabled = rx_mode_enable && (ndev->flags & IFF_PROMISC);
bool allmulti_enabled = rx_mode_enable && (ndev->flags & IFF_ALLMULTI); bool allmulti_enabled = rx_mode_enable && (ndev->flags & IFF_ALLMULTI);
bool broadcast_enabled = rx_mode_enable; bool broadcast_enabled = rx_mode_enable;
...@@ -796,17 +738,6 @@ void mlx5e_set_rx_mode_core(struct mlx5e_priv *priv) ...@@ -796,17 +738,6 @@ void mlx5e_set_rx_mode_core(struct mlx5e_priv *priv)
ea->broadcast_enabled = broadcast_enabled; 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) void mlx5e_init_eth_addr(struct mlx5e_priv *priv)
{ {
ether_addr_copy(priv->eth_addr.broadcast.addr, priv->netdev->broadcast); 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) ...@@ -929,7 +860,7 @@ static void mlx5e_destroy_vlan_flow_table(struct mlx5e_priv *priv)
mlx5_destroy_flow_table(priv->ft.vlan); 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; int err;
...@@ -941,16 +872,24 @@ int mlx5e_open_flow_table(struct mlx5e_priv *priv) ...@@ -941,16 +872,24 @@ int mlx5e_open_flow_table(struct mlx5e_priv *priv)
if (err) if (err)
goto err_destroy_main_flow_table; 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; return 0;
err_destroy_vlan_flow_table:
mlx5e_destroy_vlan_flow_table(priv);
err_destroy_main_flow_table: err_destroy_main_flow_table:
mlx5e_destroy_main_flow_table(priv); mlx5e_destroy_main_flow_table(priv);
return err; 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_vlan_flow_table(priv);
mlx5e_destroy_main_flow_table(priv); mlx5e_destroy_main_flow_table(priv);
} }
...@@ -82,6 +82,47 @@ static void mlx5e_update_carrier_work(struct work_struct *work) ...@@ -82,6 +82,47 @@ static void mlx5e_update_carrier_work(struct work_struct *work)
mutex_unlock(&priv->state_lock); 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) void mlx5e_update_stats(struct mlx5e_priv *priv)
{ {
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
...@@ -202,6 +243,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv) ...@@ -202,6 +243,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
s->tx_csum_offload = s->tx_packets - tx_offload_none; s->tx_csum_offload = s->tx_packets - tx_offload_none;
s->rx_csum_good = s->rx_packets - s->rx_csum_none; s->rx_csum_good = s->rx_packets - s->rx_csum_none;
mlx5e_update_pport_counters(priv);
free_out: free_out:
kvfree(out); kvfree(out);
} }
...@@ -307,6 +349,7 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, ...@@ -307,6 +349,7 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
rq->netdev = c->netdev; rq->netdev = c->netdev;
rq->channel = c; rq->channel = c;
rq->ix = c->ix; rq->ix = c->ix;
rq->priv = c->priv;
return 0; return 0;
...@@ -324,8 +367,7 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq) ...@@ -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) static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param)
{ {
struct mlx5e_channel *c = rq->channel; struct mlx5e_priv *priv = rq->priv;
struct mlx5e_priv *priv = c->priv;
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
void *in; void *in;
...@@ -392,11 +434,7 @@ static int mlx5e_modify_rq(struct mlx5e_rq *rq, int curr_state, int next_state) ...@@ -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) static void mlx5e_disable_rq(struct mlx5e_rq *rq)
{ {
struct mlx5e_channel *c = rq->channel; mlx5_core_destroy_rq(rq->priv->mdev, rq->rqn);
struct mlx5e_priv *priv = c->priv;
struct mlx5_core_dev *mdev = priv->mdev;
mlx5_core_destroy_rq(mdev, rq->rqn);
} }
static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq) 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, ...@@ -740,6 +778,7 @@ static int mlx5e_create_cq(struct mlx5e_channel *c,
} }
cq->channel = c; cq->channel = c;
cq->priv = priv;
return 0; return 0;
} }
...@@ -751,8 +790,7 @@ static void mlx5e_destroy_cq(struct mlx5e_cq *cq) ...@@ -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) static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
{ {
struct mlx5e_channel *c = cq->channel; struct mlx5e_priv *priv = cq->priv;
struct mlx5e_priv *priv = c->priv;
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5_core_cq *mcq = &cq->mcq; 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) ...@@ -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) static void mlx5e_disable_cq(struct mlx5e_cq *cq)
{ {
struct mlx5e_channel *c = cq->channel; struct mlx5e_priv *priv = cq->priv;
struct mlx5e_priv *priv = c->priv;
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
mlx5_core_destroy_cq(mdev, &cq->mcq); mlx5_core_destroy_cq(mdev, &cq->mcq);
...@@ -1119,112 +1156,419 @@ static void mlx5e_close_channels(struct mlx5e_priv *priv) ...@@ -1119,112 +1156,419 @@ static void mlx5e_close_channels(struct mlx5e_priv *priv)
kfree(priv->channel); kfree(priv->channel);
} }
static int mlx5e_open_tis(struct mlx5e_priv *priv, int tc) static int mlx5e_rx_hash_fn(int hfunc)
{ {
struct mlx5_core_dev *mdev = priv->mdev; return (hfunc == ETH_RSS_HASH_TOP) ?
u32 in[MLX5_ST_SZ_DW(create_tis_in)]; MLX5_RX_HASH_FN_TOEPLITZ :
void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); MLX5_RX_HASH_FN_INVERTED_XOR8;
}
memset(in, 0, sizeof(in)); static int mlx5e_bits_invert(unsigned long a, int size)
{
int inv = 0;
int i;
MLX5_SET(tisc, tisc, prio, tc); for (i = 0; i < size; i++)
MLX5_SET(tisc, tisc, transport_domain, priv->tdn); inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i;
return mlx5_core_create_tis(mdev, in, sizeof(in), &priv->tisn[tc]); return inv;
} }
static void mlx5e_close_tis(struct mlx5e_priv *priv, int tc) static void mlx5e_fill_rqt_rqns(struct mlx5e_priv *priv, void *rqtc,
enum mlx5e_rqt_ix rqt_ix)
{ {
mlx5_core_destroy_tis(priv->mdev, priv->tisn[tc]); 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_open_tises(struct mlx5e_priv *priv) 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 err;
int tc;
for (tc = 0; tc < priv->params.num_tc; tc++) { log_sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 0 :
err = mlx5e_open_tis(priv, tc); priv->params.rx_hash_log_tbl_sz;
if (err) sz = 1 << log_sz;
goto err_close_tises;
}
return 0; inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
in = mlx5_vzalloc(inlen);
if (!in)
return -ENOMEM;
err_close_tises: rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
for (tc--; tc >= 0; tc--)
mlx5e_close_tis(priv, tc); MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
mlx5e_fill_rqt_rqns(priv, rqtc, rqt_ix);
err = mlx5_core_create_rqt(mdev, in, inlen, &priv->rqtn[rqt_ix]);
kvfree(in);
return err; return err;
} }
static void mlx5e_close_tises(struct mlx5e_priv *priv) static int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
{ {
int tc; struct mlx5_core_dev *mdev = priv->mdev;
u32 *in;
void *rqtc;
int inlen;
int log_sz;
int sz;
int err;
for (tc = 0; tc < priv->params.num_tc; tc++) log_sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 0 :
mlx5e_close_tis(priv, tc); 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 int mlx5e_rx_hash_fn(int hfunc) static void mlx5e_destroy_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
{ {
return (hfunc == ETH_RSS_HASH_TOP) ? mlx5_core_destroy_rqt(priv->mdev, priv->rqtn[rqt_ix]);
MLX5_RX_HASH_FN_TOEPLITZ :
MLX5_RX_HASH_FN_INVERTED_XOR8;
} }
static int mlx5e_bits_invert(unsigned long a, int size) static void mlx5e_redirect_rqts(struct mlx5e_priv *priv)
{ {
int inv = 0; mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT);
int i; mlx5e_redirect_rqt(priv, MLX5E_SINGLE_RQ_RQT);
}
for (i = 0; i < size; i++) static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i; {
if (!priv->params.lro_en)
return;
return inv; #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_open_rqt(struct mlx5e_priv *priv) static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
{ {
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
u32 *in;
void *rqtc; void *in;
void *tirc;
int inlen; int inlen;
int err; int err;
int log_tbl_sz = priv->params.rx_hash_log_tbl_sz;
int sz = 1 << log_tbl_sz;
int i;
inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz; inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
in = mlx5_vzalloc(inlen); in = mlx5_vzalloc(inlen);
if (!in) if (!in)
return -ENOMEM; return -ENOMEM;
rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context); MLX5_SET(modify_tir_in, in, bitmask.lro, 1);
tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
MLX5_SET(rqtc, rqtc, rqt_actual_size, sz); mlx5e_build_tir_ctx_lro(tirc, priv);
MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
for (i = 0; i < sz; i++) { err = mlx5_core_modify_tir(mdev, priv->tirn[tt], in, inlen);
int ix = i;
if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR) kvfree(in);
ix = mlx5e_bits_invert(i, log_tbl_sz);
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);
ix = ix % priv->params.num_channels; err = mlx5e_set_dev_port_mtu(netdev);
MLX5_SET(rqtc, rqtc, rq_num[i], priv->channel[ix]->rq.rqn); 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;
} }
err = mlx5_core_create_rqt(mdev, in, inlen, &priv->rqtn); mlx5e_update_carrier(priv);
mlx5e_redirect_rqts(priv);
kvfree(in); 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; return err;
} }
static void mlx5e_close_rqt(struct mlx5e_priv *priv) int mlx5e_close_locked(struct net_device *netdev)
{ {
mlx5_core_destroy_rqt(priv->mdev, priv->rqtn); 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, &param->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, &param->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) 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) ...@@ -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); 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 |\ #define MLX5_HASH_IP (MLX5_HASH_FIELD_SEL_SRC_IP |\
MLX5_HASH_FIELD_SEL_DST_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) ...@@ -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_DST_IP |\
MLX5_HASH_FIELD_SEL_IPSEC_SPI) MLX5_HASH_FIELD_SEL_IPSEC_SPI)
if (priv->params.lro_en) { mlx5e_build_tir_ctx_lro(tirc, priv);
MLX5_SET(tirc, tirc, lro_enable_mask,
MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO | MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
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]));
}
switch (tt) { switch (tt) {
case MLX5E_TT_ANY: case MLX5E_TT_ANY:
MLX5_SET(tirc, tirc, disp_type, MLX5_SET(tirc, tirc, indirect_table,
MLX5_TIRC_DISP_TYPE_DIRECT); priv->rqtn[MLX5E_SINGLE_RQ_RQT]);
MLX5_SET(tirc, tirc, inline_rqn, MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
priv->channel[0]->rq.rqn);
break; break;
default: default:
MLX5_SET(tirc, tirc, disp_type,
MLX5_TIRC_DISP_TYPE_INDIRECT);
MLX5_SET(tirc, tirc, indirect_table, MLX5_SET(tirc, tirc, indirect_table,
priv->rqtn); priv->rqtn[MLX5E_INDIRECTION_RQT]);
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_SET(tirc, tirc, rx_hash_fn,
mlx5e_rx_hash_fn(priv->params.rss_hfunc)); mlx5e_rx_hash_fn(priv->params.rss_hfunc));
if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) { 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) ...@@ -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; struct mlx5_core_dev *mdev = priv->mdev;
u32 *in; u32 *in;
...@@ -1390,184 +1721,37 @@ static int mlx5e_open_tir(struct mlx5e_priv *priv, int tt) ...@@ -1390,184 +1721,37 @@ static int mlx5e_open_tir(struct mlx5e_priv *priv, int tt)
return err; 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]); 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 err;
int i; int i;
for (i = 0; i < MLX5E_NUM_TT; i++) { for (i = 0; i < MLX5E_NUM_TT; i++) {
err = mlx5e_open_tir(priv, i); err = mlx5e_create_tir(priv, i);
if (err) if (err)
goto err_close_tirs; goto err_destroy_tirs;
} }
return 0; return 0;
err_close_tirs: err_destroy_tirs:
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
mlx5e_close_tir(priv, i); mlx5e_destroy_tir(priv, i);
return err; return err;
} }
static void mlx5e_close_tirs(struct mlx5e_priv *priv) static void mlx5e_destroy_tirs(struct mlx5e_priv *priv)
{ {
int i; int i;
for (i = 0; i < MLX5E_NUM_TT; i++) for (i = 0; i < MLX5E_NUM_TT; i++)
mlx5e_close_tir(priv, i); mlx5e_destroy_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;
} }
static struct rtnl_link_stats64 * static struct rtnl_link_stats64 *
...@@ -1631,11 +1815,15 @@ static int mlx5e_set_features(struct net_device *netdev, ...@@ -1631,11 +1815,15 @@ static int mlx5e_set_features(struct net_device *netdev,
mlx5e_close_locked(priv->netdev); mlx5e_close_locked(priv->netdev);
priv->params.lro_en = !!(features & NETIF_F_LRO); 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) if (was_opened)
err = mlx5e_open_locked(priv->netdev); err = mlx5e_open_locked(priv->netdev);
} }
mutex_unlock(&priv->state_lock);
if (changes & NETIF_F_HW_VLAN_CTAG_FILTER) { if (changes & NETIF_F_HW_VLAN_CTAG_FILTER) {
if (features & NETIF_F_HW_VLAN_CTAG_FILTER) if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
mlx5e_enable_vlan_filter(priv); mlx5e_enable_vlan_filter(priv);
...@@ -1643,8 +1831,6 @@ static int mlx5e_set_features(struct net_device *netdev, ...@@ -1643,8 +1831,6 @@ static int mlx5e_set_features(struct net_device *netdev,
mlx5e_disable_vlan_filter(priv); mlx5e_disable_vlan_filter(priv);
} }
mutex_unlock(&priv->state_lock);
return 0; return 0;
} }
...@@ -1891,16 +2077,73 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) ...@@ -1891,16 +2077,73 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
goto err_dealloc_transport_domain; goto err_dealloc_transport_domain;
} }
err = mlx5e_create_tises(priv);
if (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); err = register_netdev(netdev);
if (err) { if (err) {
mlx5_core_err(mdev, "register_netdev failed, %d\n", err); mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
goto err_destroy_mkey; goto err_destroy_flow_tables;
} }
mlx5e_enable_async_events(priv); mlx5e_enable_async_events(priv);
schedule_work(&priv->set_rx_mode_work);
return priv; 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: err_destroy_mkey:
mlx5_core_destroy_mkey(mdev, &priv->mr); mlx5_core_destroy_mkey(mdev, &priv->mr);
...@@ -1924,13 +2167,22 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv) ...@@ -1924,13 +2167,22 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
struct mlx5e_priv *priv = vpriv; struct mlx5e_priv *priv = vpriv;
struct net_device *netdev = priv->netdev; 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); 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_core_destroy_mkey(priv->mdev, &priv->mr);
mlx5_dealloc_transport_domain(priv->mdev, priv->tdn); mlx5_dealloc_transport_domain(priv->mdev, priv->tdn);
mlx5_core_dealloc_pd(priv->mdev, priv->pdn); mlx5_core_dealloc_pd(priv->mdev, priv->pdn);
mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar); mlx5_unmap_free_uar(priv->mdev, &priv->cq_uar);
mlx5e_disable_async_events(priv);
flush_scheduled_work();
free_netdev(netdev); free_netdev(netdev);
} }
......
...@@ -163,6 +163,18 @@ int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, int inlen, ...@@ -163,6 +163,18 @@ int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, int inlen,
return err; 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) void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn)
{ {
u32 in[MLX5_ST_SZ_DW(destroy_tir_out)]; 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, ...@@ -375,6 +387,18 @@ int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen,
return err; 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) void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn)
{ {
u32 in[MLX5_ST_SZ_DW(destroy_rqt_in)]; 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); ...@@ -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); 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, int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, int inlen,
u32 *tirn); 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); 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, int mlx5_core_create_tis(struct mlx5_core_dev *dev, u32 *in, int inlen,
u32 *tisn); u32 *tisn);
...@@ -63,6 +65,8 @@ int mlx5_core_arm_xsrq(struct mlx5_core_dev *dev, u32 rmpn, u16 lwm); ...@@ -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, int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen,
u32 *rqtn); 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); void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn);
#endif /* __TRANSOBJ_H__ */ #endif /* __TRANSOBJ_H__ */
...@@ -1182,6 +1182,16 @@ enum { ...@@ -1182,6 +1182,16 @@ enum {
MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR = 0x40, 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) static inline u16 mlx5_to_sw_pkey_sz(int pkey_sz)
{ {
if (pkey_sz > MLX5_MAX_LOG_PKEY_TABLE) if (pkey_sz > MLX5_MAX_LOG_PKEY_TABLE)
......
...@@ -103,6 +103,7 @@ enum { ...@@ -103,6 +103,7 @@ enum {
MLX5_REG_PMTU = 0x5003, MLX5_REG_PMTU = 0x5003,
MLX5_REG_PTYS = 0x5004, MLX5_REG_PTYS = 0x5004,
MLX5_REG_PAOS = 0x5006, MLX5_REG_PAOS = 0x5006,
MLX5_REG_PPCNT = 0x5008,
MLX5_REG_PMAOS = 0x5012, MLX5_REG_PMAOS = 0x5012,
MLX5_REG_PUDE = 0x5009, MLX5_REG_PUDE = 0x5009,
MLX5_REG_PMPE = 0x5010, MLX5_REG_PMPE = 0x5010,
......
...@@ -4050,6 +4050,13 @@ struct mlx5_ifc_modify_tis_in_bits { ...@@ -4050,6 +4050,13 @@ struct mlx5_ifc_modify_tis_in_bits {
struct mlx5_ifc_tisc_bits ctx; 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 { struct mlx5_ifc_modify_tir_out_bits {
u8 status[0x8]; u8 status[0x8];
u8 reserved_0[0x18]; u8 reserved_0[0x18];
...@@ -4071,7 +4078,7 @@ struct mlx5_ifc_modify_tir_in_bits { ...@@ -4071,7 +4078,7 @@ struct mlx5_ifc_modify_tir_in_bits {
u8 reserved_3[0x20]; u8 reserved_3[0x20];
u8 modify_bitmask[0x40]; struct mlx5_ifc_modify_tir_bitmask_bits bitmask;
u8 reserved_4[0x40]; u8 reserved_4[0x40];
...@@ -4116,6 +4123,13 @@ struct mlx5_ifc_modify_rqt_out_bits { ...@@ -4116,6 +4123,13 @@ struct mlx5_ifc_modify_rqt_out_bits {
u8 reserved_1[0x40]; 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 { struct mlx5_ifc_modify_rqt_in_bits {
u8 opcode[0x10]; u8 opcode[0x10];
u8 reserved_0[0x10]; u8 reserved_0[0x10];
...@@ -4128,7 +4142,7 @@ struct mlx5_ifc_modify_rqt_in_bits { ...@@ -4128,7 +4142,7 @@ struct mlx5_ifc_modify_rqt_in_bits {
u8 reserved_3[0x20]; u8 reserved_3[0x20];
u8 modify_bitmask[0x40]; struct mlx5_ifc_rqt_bitmask_bits bitmask;
u8 reserved_4[0x40]; u8 reserved_4[0x40];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment