* [net V2 1/8] net/mlx5e: Don't override vport admin link state in switchdev mode
From: Saeed Mahameed @ 2018-03-26 21:04 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Jianbo Liu, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Jianbo Liu <jianbol@mellanox.com>
The vport admin original link state will be re-applied after returning
back to legacy mode, it is not right to change the admin link state value
when in switchdev mode.
Use direct vport commands to alter logical vport state in netdev
representor open/close flows rather than the administrative eswitch API.
Fixes: 20a1ea674783 ('net/mlx5e: Support VF vport link state control for SRIOV switchdev mode')
Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 363d8dcb7f17..0273c233bc85 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -668,7 +668,6 @@ static int mlx5e_rep_open(struct net_device *dev)
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
- struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
int err;
mutex_lock(&priv->state_lock);
@@ -676,8 +675,9 @@ static int mlx5e_rep_open(struct net_device *dev)
if (err)
goto unlock;
- if (!mlx5_eswitch_set_vport_state(esw, rep->vport,
- MLX5_ESW_VPORT_ADMIN_STATE_UP))
+ if (!mlx5_modify_vport_admin_state(priv->mdev,
+ MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
+ rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_UP))
netif_carrier_on(dev);
unlock:
@@ -690,11 +690,12 @@ static int mlx5e_rep_close(struct net_device *dev)
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
- struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
int ret;
mutex_lock(&priv->state_lock);
- (void)mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
+ mlx5_modify_vport_admin_state(priv->mdev,
+ MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
+ rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
ret = mlx5e_close_locked(dev);
mutex_unlock(&priv->state_lock);
return ret;
--
2.14.3
^ permalink raw reply related
* [pull request][net V2 0/8] Mellanox, mlx5 fixes 2018-03-23
From: Saeed Mahameed @ 2018-03-26 21:04 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
Hi Dave,
The following series includes fixes for mlx5 netdev and eswitch.
v1->v2:
- Fixed commit message quotation marks in patch #7
For -stable v4.12
('net/mlx5e: Avoid using the ipv6 stub in the TC offload neigh update path')
('net/mlx5e: Fix traffic being dropped on VF representor')
For -stable v4.13
('net/mlx5e: Fix memory usage issues in offloading TC flows')
('net/mlx5e: Verify coalescing parameters in range')
For -stable v4.14
('net/mlx5e: Don't override vport admin link state in switchdev mode')
For -stable v4.15
('108b2b6d5c02 net/mlx5e: Sync netdev vxlan ports at open')
Please pull and let me know if there's any problem.
Thanks,
Saeed.
---
The following changes since commit 3c82b372a9f44aa224b8d5106ff6f1ad516fa8a8:
net: dsa: mt7530: fix module autoloading for OF platform drivers (2018-03-26 13:09:42 -0400)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-fixes-2018-03-23
for you to fetch changes up to a117f73dc2430443f23e18367fa545981129c1a6:
net/mlx5e: Sync netdev vxlan ports at open (2018-03-26 13:59:08 -0700)
----------------------------------------------------------------
mlx5-fixes-2018-03-23
----------------------------------------------------------------
Jianbo Liu (2):
net/mlx5e: Don't override vport admin link state in switchdev mode
net/mlx5e: Fix memory usage issues in offloading TC flows
Moshe Shemesh (1):
net/mlx5e: Verify coalescing parameters in range
Or Gerlitz (3):
net/mlx5e: Use 32 bits to store VF representor SQ number
net/mlx5: Make eswitch support to depend on switchdev
net/mlx5e: Avoid using the ipv6 stub in the TC offload neigh update path
Roi Dayan (1):
net/mlx5e: Fix traffic being dropped on VF representor
Shahar Klein (1):
net/mlx5e: Sync netdev vxlan ports at open
drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 2 +-
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 17 +++++++++++
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 13 ++++-----
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 34 ++++++++++++----------
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 18 ++++++------
5 files changed, 51 insertions(+), 33 deletions(-)
^ permalink raw reply
* [net V2 2/8] net/mlx5e: Use 32 bits to store VF representor SQ number
From: Saeed Mahameed @ 2018-03-26 21:04 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Or Gerlitz, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Or Gerlitz <ogerlitz@mellanox.com>
SQs are 32 and not 16 bits, hence it's wrong to use only 16 bits to
store the sq number for which are going to set steering rule, fix that.
Fixes: cb67b832921c ('net/mlx5e: Introduce SRIOV VF representors')
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Mark Bloch <markb@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 0273c233bc85..738554a6c69f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -209,7 +209,7 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep,
- u16 *sqns_array, int sqns_num)
+ u32 *sqns_array, int sqns_num)
{
struct mlx5_flow_handle *flow_rule;
struct mlx5e_rep_priv *rpriv;
@@ -255,9 +255,9 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
struct mlx5e_channel *c;
int n, tc, num_sqs = 0;
int err = -ENOMEM;
- u16 *sqs;
+ u32 *sqs;
- sqs = kcalloc(priv->channels.num * priv->channels.params.num_tc, sizeof(u16), GFP_KERNEL);
+ sqs = kcalloc(priv->channels.num * priv->channels.params.num_tc, sizeof(*sqs), GFP_KERNEL);
if (!sqs)
goto out;
--
2.14.3
^ permalink raw reply related
* [net V2 3/8] net/mlx5: Make eswitch support to depend on switchdev
From: Saeed Mahameed @ 2018-03-26 21:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Or Gerlitz, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Or Gerlitz <ogerlitz@mellanox.com>
Add dependancy for switchdev to be congfigured as any user-space control
plane SW is expected to use the HW switchdev ID to locate the representors
related to VFs of a certain PF and apply SW/offloaded switching on them.
Fixes: e80541ecabd5 ('net/mlx5: Add CONFIG_MLX5_ESWITCH Kconfig')
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Mark Bloch <markb@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++--
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 --
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index 25deaa5a534c..c032319f1cb9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -46,7 +46,7 @@ config MLX5_MPFS
config MLX5_ESWITCH
bool "Mellanox Technologies MLX5 SRIOV E-Switch support"
- depends on MLX5_CORE_EN
+ depends on MLX5_CORE_EN && NET_SWITCHDEV
default y
---help---
Mellanox Technologies Ethernet SRIOV E-Switch support in ConnectX NIC.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index da94c8cba5ee..e35859657217 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4069,7 +4069,7 @@ static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
}
}
-#if IS_ENABLED(CONFIG_NET_SWITCHDEV) && IS_ENABLED(CONFIG_MLX5_ESWITCH)
+#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
static const struct switchdev_ops mlx5e_switchdev_ops = {
.switchdev_port_attr_get = mlx5e_attr_get,
};
@@ -4175,7 +4175,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
mlx5e_set_netdev_dev_addr(netdev);
-#if IS_ENABLED(CONFIG_NET_SWITCHDEV) && IS_ENABLED(CONFIG_MLX5_ESWITCH)
+#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
if (MLX5_VPORT_MANAGER(mdev))
netdev->switchdev_ops = &mlx5e_switchdev_ops;
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 738554a6c69f..5ece289548ad 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -900,9 +900,7 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
-#ifdef CONFIG_NET_SWITCHDEV
netdev->switchdev_ops = &mlx5e_rep_switchdev_ops;
-#endif
netdev->features |= NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
netdev->hw_features |= NETIF_F_HW_TC;
--
2.14.3
^ permalink raw reply related
* [net V2 4/8] net/mlx5e: Verify coalescing parameters in range
From: Saeed Mahameed @ 2018-03-26 21:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Moshe Shemesh, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Moshe Shemesh <moshe@mellanox.com>
Add check of coalescing parameters received through ethtool are within
range of values supported by the HW.
Driver gets the coalescing rx/tx-usecs and rx/tx-frames as set by the
users through ethtool. The ethtool support up to 32 bit value for each.
However, mlx5 modify cq limits the coalescing time parameter to 12 bit
and coalescing frames parameters to 16 bits.
Return out of range error if user tries to set these parameters to
higher values.
Fixes: f62b8bb8f2d3 ('net/mlx5: Extend mlx5_core to support ConnectX-4 Ethernet functionality')
Signed-off-by: Moshe Shemesh <moshe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index cc8048f68f11..59ebfdae6695 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -477,6 +477,9 @@ static int mlx5e_get_coalesce(struct net_device *netdev,
return mlx5e_ethtool_get_coalesce(priv, coal);
}
+#define MLX5E_MAX_COAL_TIME MLX5_MAX_CQ_PERIOD
+#define MLX5E_MAX_COAL_FRAMES MLX5_MAX_CQ_COUNT
+
static void
mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
{
@@ -511,6 +514,20 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
if (!MLX5_CAP_GEN(mdev, cq_moderation))
return -EOPNOTSUPP;
+ if (coal->tx_coalesce_usecs > MLX5E_MAX_COAL_TIME ||
+ coal->rx_coalesce_usecs > MLX5E_MAX_COAL_TIME) {
+ netdev_info(priv->netdev, "%s: maximum coalesce time supported is %lu usecs\n",
+ __func__, MLX5E_MAX_COAL_TIME);
+ return -ERANGE;
+ }
+
+ if (coal->tx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES ||
+ coal->rx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES) {
+ netdev_info(priv->netdev, "%s: maximum coalesced frames supported is %lu\n",
+ __func__, MLX5E_MAX_COAL_FRAMES);
+ return -ERANGE;
+ }
+
mutex_lock(&priv->state_lock);
new_channels.params = priv->channels.params;
--
2.14.3
^ permalink raw reply related
* [net V2 5/8] net/mlx5e: Fix traffic being dropped on VF representor
From: Saeed Mahameed @ 2018-03-26 21:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Roi Dayan, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Roi Dayan <roid@mellanox.com>
Increase representor netdev RQ size to avoid dropped packets.
The current size (two) is just too small to keep up with
conventional slow path traffic patterns.
Also match the SQ size to the RQ size.
Fixes: cb67b832921c ("net/mlx5e: Introduce SRIOV VF representors")
Signed-off-by: Roi Dayan <roid@mellanox.com>
Reviewed-by: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 5ece289548ad..9a5a2a7eeab3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -44,6 +44,11 @@
#include "en_tc.h"
#include "fs_core.h"
+#define MLX5E_REP_PARAMS_LOG_SQ_SIZE \
+ max(0x6, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
+#define MLX5E_REP_PARAMS_LOG_RQ_SIZE \
+ max(0x6, MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)
+
static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
static void mlx5e_rep_get_drvinfo(struct net_device *dev,
@@ -878,9 +883,9 @@ static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
- params->log_sq_size = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
+ params->log_sq_size = MLX5E_REP_PARAMS_LOG_SQ_SIZE;
params->rq_wq_type = MLX5_WQ_TYPE_LINKED_LIST;
- params->log_rq_size = MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE;
+ params->log_rq_size = MLX5E_REP_PARAMS_LOG_RQ_SIZE;
params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
mlx5e_set_rx_cq_mode_params(params, cq_period_mode);
--
2.14.3
^ permalink raw reply related
* [net V2 6/8] net/mlx5e: Fix memory usage issues in offloading TC flows
From: Saeed Mahameed @ 2018-03-26 21:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Jianbo Liu, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Jianbo Liu <jianbol@mellanox.com>
For NIC flows, the parsed attributes are not freed when we exit
successfully from mlx5e_configure_flower().
There is possible double free for eswitch flows. If error is returned
from rhashtable_insert_fast(), the parse attrs will be freed in
mlx5e_tc_del_flow(), but they will be freed again before exiting
mlx5e_configure_flower().
To fix both issues we do the following:
(1) change the condition that determines if to issue the free call to
check if this flow is NIC flow, or it does not have encap action.
(2) reorder the code such that that the check and free calls are done
before we attempt to add into the hash table.
Fixes: 232c001398ae ('net/mlx5e: Add support to neighbour update flow')
Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index fa86a1466718..ae11678a31e8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -2608,19 +2608,19 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
if (err != -EAGAIN)
flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
+ if (!(flow->flags & MLX5E_TC_FLOW_ESWITCH) ||
+ !(flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP))
+ kvfree(parse_attr);
+
err = rhashtable_insert_fast(&tc->ht, &flow->node,
tc->ht_params);
- if (err)
- goto err_del_rule;
+ if (err) {
+ mlx5e_tc_del_flow(priv, flow);
+ kfree(flow);
+ }
- if (flow->flags & MLX5E_TC_FLOW_ESWITCH &&
- !(flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP))
- kvfree(parse_attr);
return err;
-err_del_rule:
- mlx5e_tc_del_flow(priv, flow);
-
err_free:
kvfree(parse_attr);
kfree(flow);
--
2.14.3
^ permalink raw reply related
* [net V2 7/8] net/mlx5e: Avoid using the ipv6 stub in the TC offload neigh update path
From: Saeed Mahameed @ 2018-03-26 21:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Or Gerlitz, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Or Gerlitz <ogerlitz@mellanox.com>
Currently we use the global ipv6_stub var to access the ipv6 global
nd table. This practice gets us to troubles when the stub is only partially
set e.g when ipv6 is loaded under the disabled policy. In this case, as of commit
343d60aada5a ("ipv6: change ipv6_stub_impl.ipv6_dst_lookup to take net argument")
the stub is not null, but stub->nd_tbl is and we crash.
As we can access the ipv6 nd_tbl directly, the fix is just to avoid the
reference through the stub. There is one place in the code where we
issue ipv6 route lookup and keep doing it through the stub, but that
mentioned commit makes sure we get -EAFNOSUPPORT from the stack.
Fixes: 232c001398ae ("net/mlx5e: Add support to neighbour update flow")
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Aviv Heller <avivh@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 6 +++---
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 9a5a2a7eeab3..500d817d2b0a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -293,7 +293,7 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
static void mlx5e_rep_neigh_update_init_interval(struct mlx5e_rep_priv *rpriv)
{
#if IS_ENABLED(CONFIG_IPV6)
- unsigned long ipv6_interval = NEIGH_VAR(&ipv6_stub->nd_tbl->parms,
+ unsigned long ipv6_interval = NEIGH_VAR(&nd_tbl.parms,
DELAY_PROBE_TIME);
#else
unsigned long ipv6_interval = ~0UL;
@@ -429,7 +429,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
case NETEVENT_NEIGH_UPDATE:
n = ptr;
#if IS_ENABLED(CONFIG_IPV6)
- if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
+ if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
#else
if (n->tbl != &arp_tbl)
#endif
@@ -477,7 +477,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
* done per device delay prob time parameter.
*/
#if IS_ENABLED(CONFIG_IPV6)
- if (!p->dev || (p->tbl != ipv6_stub->nd_tbl && p->tbl != &arp_tbl))
+ if (!p->dev || (p->tbl != &nd_tbl && p->tbl != &arp_tbl))
#else
if (!p->dev || p->tbl != &arp_tbl)
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index ae11678a31e8..43234cabf444 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -963,7 +963,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
tbl = &arp_tbl;
#if IS_ENABLED(CONFIG_IPV6)
else if (m_neigh->family == AF_INET6)
- tbl = ipv6_stub->nd_tbl;
+ tbl = &nd_tbl;
#endif
else
return;
--
2.14.3
^ permalink raw reply related
* [net V2 8/8] net/mlx5e: Sync netdev vxlan ports at open
From: Saeed Mahameed @ 2018-03-26 21:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Shahar Klein, Saeed Mahameed
In-Reply-To: <20180326210505.11007-1-saeedm@mellanox.com>
From: Shahar Klein <shahark@mellanox.com>
When mlx5_core is loaded it is expected to sync ports
with all vxlan devices so it can support vxlan encap/decap.
This is done via udp_tunnel_get_rx_info(). Currently this
call is set in mlx5e_nic_enable() and if the netdev is not in
NETREG_REGISTERED state it will not be called.
Normally on load the netdev state is not NETREG_REGISTERED
so udp_tunnel_get_rx_info() will not be called.
Moving udp_tunnel_get_rx_info() to mlx5e_open() so
it will be called on netdev UP event and allow encap/decap.
Fixes: 610e89e05c3f ("net/mlx5e: Don't sync netdev state when not registered")
Signed-off-by: Shahar Klein <shahark@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index e35859657217..9b4827d36e3e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2572,6 +2572,9 @@ int mlx5e_open(struct net_device *netdev)
mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
mutex_unlock(&priv->state_lock);
+ if (mlx5e_vxlan_allowed(priv->mdev))
+ udp_tunnel_get_rx_info(netdev);
+
return err;
}
@@ -4327,12 +4330,6 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
#ifdef CONFIG_MLX5_CORE_EN_DCB
mlx5e_dcbnl_init_app(priv);
#endif
- /* Device already registered: sync netdev system state */
- if (mlx5e_vxlan_allowed(mdev)) {
- rtnl_lock();
- udp_tunnel_get_rx_info(netdev);
- rtnl_unlock();
- }
queue_work(priv->wq, &priv->set_rx_mode_work);
--
2.14.3
^ permalink raw reply related
* [PATCH 5/6] net/ipv4: Update ip_tunnel_metadata_cnt static key to modern api
From: Davidlohr Bueso @ 2018-03-26 21:09 UTC (permalink / raw)
To: peterz, mingo, akpm
Cc: linux-kernel, Davidlohr Bueso, David S . Miller, netdev,
Davidlohr Bueso
In-Reply-To: <20180326210929.5244-1-dave@stgolabs.net>
No changes in refcount semantics -- key init is false; replace
static_key_slow_inc|dec with static_branch_inc|dec
static_key_false with static_branch_unlikely
Added a '_key' suffix to i2c_trace_msg, for better self
documentation.
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
---
include/net/ip_tunnels.h | 4 ++--
net/ipv4/ip_tunnel_core.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 540a4b4417bf..fc494b48a64a 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -466,12 +466,12 @@ static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstat
return (struct ip_tunnel_info *)lwtstate->data;
}
-extern struct static_key ip_tunnel_metadata_cnt;
+DECLARE_STATIC_KEY_FALSE(ip_tunnel_metadata_cnt);
/* Returns > 0 if metadata should be collected */
static inline int ip_tunnel_collect_metadata(void)
{
- return static_key_false(&ip_tunnel_metadata_cnt);
+ return static_branch_unlikely(&ip_tunnel_metadata_cnt);
}
void __init ip_tunnel_core_init(void);
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 2f39479be92f..dde671e97829 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -423,17 +423,17 @@ void __init ip_tunnel_core_init(void)
lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6);
}
-struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE;
+DEFINE_STATIC_KEY_FALSE(ip_tunnel_metadata_cnt);
EXPORT_SYMBOL(ip_tunnel_metadata_cnt);
void ip_tunnel_need_metadata(void)
{
- static_key_slow_inc(&ip_tunnel_metadata_cnt);
+ static_branch_inc(&ip_tunnel_metadata_cnt);
}
EXPORT_SYMBOL_GPL(ip_tunnel_need_metadata);
void ip_tunnel_unneed_metadata(void)
{
- static_key_slow_dec(&ip_tunnel_metadata_cnt);
+ static_branch_dec(&ip_tunnel_metadata_cnt);
}
EXPORT_SYMBOL_GPL(ip_tunnel_unneed_metadata);
--
2.13.6
^ permalink raw reply related
* [PATCH 6/6] net/sock: Update memalloc_socks static key to modern api
From: Davidlohr Bueso @ 2018-03-26 21:09 UTC (permalink / raw)
To: peterz, mingo, akpm
Cc: linux-kernel, Davidlohr Bueso, David S . Miller, netdev,
Davidlohr Bueso
In-Reply-To: <20180326210929.5244-1-dave@stgolabs.net>
No changes in refcount semantics -- key init is false; replace
static_key_slow_inc|dec with static_branch_inc|dec
static_key_false with static_branch_unlikely
Added a '_key' suffix to memalloc_socks, for better self
documentation.
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
---
include/net/sock.h | 4 ++--
net/core/sock.c | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 8c428c6847af..15d676365743 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -803,10 +803,10 @@ static inline bool sock_flag(const struct sock *sk, enum sock_flags flag)
}
#ifdef CONFIG_NET
-extern struct static_key memalloc_socks;
+DECLARE_STATIC_KEY_FALSE(memalloc_socks_key);
static inline int sk_memalloc_socks(void)
{
- return static_key_false(&memalloc_socks);
+ return static_branch_unlikely(&memalloc_socks_key);
}
#else
diff --git a/net/core/sock.c b/net/core/sock.c
index e689496dfd8a..670f35803411 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -323,8 +323,8 @@ EXPORT_SYMBOL(sysctl_optmem_max);
int sysctl_tstamp_allow_data __read_mostly = 1;
-struct static_key memalloc_socks = STATIC_KEY_INIT_FALSE;
-EXPORT_SYMBOL_GPL(memalloc_socks);
+DEFINE_STATIC_KEY_FALSE(memalloc_socks_key);
+EXPORT_SYMBOL_GPL(memalloc_socks_key);
/**
* sk_set_memalloc - sets %SOCK_MEMALLOC
@@ -338,7 +338,7 @@ void sk_set_memalloc(struct sock *sk)
{
sock_set_flag(sk, SOCK_MEMALLOC);
sk->sk_allocation |= __GFP_MEMALLOC;
- static_key_slow_inc(&memalloc_socks);
+ static_branch_inc(&memalloc_socks_key);
}
EXPORT_SYMBOL_GPL(sk_set_memalloc);
@@ -346,7 +346,7 @@ void sk_clear_memalloc(struct sock *sk)
{
sock_reset_flag(sk, SOCK_MEMALLOC);
sk->sk_allocation &= ~__GFP_MEMALLOC;
- static_key_slow_dec(&memalloc_socks);
+ static_branch_dec(&memalloc_socks_key);
/*
* SOCK_MEMALLOC is allowed to ignore rmem limits to ensure forward
--
2.13.6
^ permalink raw reply related
* Re: [PATCH v2 iproute2-next 3/6] rdma: Add CM_ID resource tracking information
From: Jason Gunthorpe @ 2018-03-26 21:15 UTC (permalink / raw)
To: Steve Wise; +Cc: David Ahern, leon, stephen, netdev, linux-rdma
In-Reply-To: <0443b8e0-17ff-1e62-51ba-ba1fa0e0d529@opengridcomputing.com>
On Mon, Mar 26, 2018 at 09:30:41AM -0500, Steve Wise wrote:
>
>
> On 3/26/2018 9:17 AM, David Ahern wrote:
> > On 2/27/18 9:07 AM, Steve Wise wrote:
> >> diff --git a/rdma/rdma.h b/rdma/rdma.h
> >> index 5809f70..e55205b 100644
> >> +++ b/rdma/rdma.h
> >> @@ -18,10 +18,12 @@
> >> #include <libmnl/libmnl.h>
> >> #include <rdma/rdma_netlink.h>
> >> #include <time.h>
> >> +#include <net/if_arp.h>
> >>
> >> #include "list.h"
> >> #include "utils.h"
> >> #include "json_writer.h"
> >> +#include <rdma/rdma_cma.h>
> >>
> > did you forget to add rdma_cma.h? I don't see that file in my repo.
>
> It is provided by the rdma-core package, upon which rdma tool now
> depends for the rdma_port_space enum.
It is a kernel bug that enum is not in an include/uapi/rdma header
Fix it there and don't try to use rdma-core headers to get kernel ABI.
Jason
^ permalink raw reply
* Re: [PATCH net-next 0/2] net: broadcom: Adaptive interrupt coalescing
From: Tal Gilboa @ 2018-03-26 21:16 UTC (permalink / raw)
To: Florian Fainelli, netdev
Cc: davem, jaedon.shin, pgynther, opendmb, michal.chan, gospo, saeedm
In-Reply-To: <20180323011933.29748-1-f.fainelli@gmail.com>
On 3/23/2018 4:19 AM, Florian Fainelli wrote:
> Hi all,
>
> This patch series adds adaptive interrupt coalescing for the Gigabit Ethernet
> drivers SYSTEMPORT and GENET.
>
> This really helps lower the interrupt count and system load, as measured by
> vmstat for a Gigabit TCP RX session:
I don't see an improvement in system load, the opposite - 42% vs. 100%
for SYSTEMPORT and 85% vs. 100% for GENET. Both with the same bandwidth.
Am I missing something? Talking about bandwidth, I would expect 941Mb/s
(assuming this is TCP over IPv4). Do you know why the reduced interrupt
rate doesn't improve bandwidth? Also, any effect on the client side (you
mentioned enabling TX moderation for SYSTEMPORT)?
>
> SYSTEMPORT:
>
> without:
>
> 1 0 0 192188 0 25472 0 0 0 0 122100 38870 1 42 57 0 0
> [ ID] Interval Transfer Bandwidth
> [ 4] 0.0-10.0 sec 1.03 GBytes 884 Mbits/sec
>
> with:
>
> 1 0 0 192288 0 25468 0 0 0 0 58806 44401 0 100 0 0 0
> [ 5] 0.0-10.0 sec 1.04 GBytes 888 Mbits/sec
>
> GENET:
>
> without:
>
> 1 0 0 1170404 0 25420 0 0 0 0 130785 63402 2 85 12 0 0
> [ ID] Interval Transfer Bandwidth
> [ 4] 0.0-10.0 sec 1.04 GBytes 888 Mbits/sec
>
> with:
>
> 1 0 0 1170560 0 25420 0 0 0 0 50610 48477 0 100 0 0 0
> [ 5] 0.0-10.0 sec 1.05 GBytes 899 Mbits/sec
>
> Please look at the implementation and let me know if you see any problems, this
> was largely inspired by bnxt_en.
>
> Thank you!
>
> Florian Fainelli (2):
> net: systemport: Implement adaptive interrupt coalescing
> net: bcmgenet: Add support for adaptive RX coalescing
>
> drivers/net/ethernet/broadcom/bcmsysport.c | 141 ++++++++++++++++++++++---
> drivers/net/ethernet/broadcom/bcmsysport.h | 14 +++
> drivers/net/ethernet/broadcom/genet/bcmgenet.c | 109 +++++++++++++++----
> drivers/net/ethernet/broadcom/genet/bcmgenet.h | 12 +++
> 4 files changed, 243 insertions(+), 33 deletions(-)
>
^ permalink raw reply
* Re: [PATCH net-next] qed*: Utilize FW 8.33.11.0
From: Jason Gunthorpe @ 2018-03-26 21:18 UTC (permalink / raw)
To: Michal Kalderon
Cc: davem, netdev, linux-rdma, linux-scsi, Tomer Tayar,
Manish Rangankar, Ariel Elior
In-Reply-To: <1522083732-26560-1-git-send-email-Michal.Kalderon@cavium.com>
On Mon, Mar 26, 2018 at 08:02:12PM +0300, Michal Kalderon wrote:
> This FW contains several fixes and features
>
> RDMA Features
> - SRQ support
> - XRC support
> - Memory window support
> - RDMA low latency queue support
> - RDMA bonding support
>
> RDMA bug fixes
> - RDMA remote invalidate during retransmit fix
> - iWARP MPA connect interop issue with RTR fix
> - iWARP Legacy DPM support
> - Fix MPA reject flow
> - iWARP error handling
> - RQ WQE validation checks
>
> MISC
> - Fix some HSI types endianity
> - New Restriction: vlan insertion in core_tx_bd_data can't be set
> for LB packets
>
> ETH
> - HW QoS offload support
> - Fix vlan, dcb and sriov flow of VF sending a packet with
> inband VLAN tag instead of default VLAN
> - Allow GRE version 1 offloads in RX flow
> - Allow VXLAN steering
>
> iSCSI / FcoE
> - Fix bd availability checking flow
> - Support 256th sge proerly in iscsi/fcoe retransmit
> - Performance improvement
> - Fix handle iSCSI command arrival with AHS and with immediate
> - Fix ipv6 traffic class configuration
>
> DEBUG
> - Update debug utilities
>
> Advance version number
>
> Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
> Signed-off-by: Tomer Tayar <Tomer.Tayar@cavium.com>
> Signed-off-by: Manish Rangankar <Manish.Rangankar@cavium.com>
> Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
> drivers/infiniband/hw/qedr/main.c | 1 +
> drivers/infiniband/hw/qedr/qedr.h | 2 +
> drivers/infiniband/hw/qedr/qedr_hsi_rdma.h | 4 +-
> drivers/infiniband/hw/qedr/verbs.c | 4 +-
> drivers/net/ethernet/qlogic/qed/qed.h | 2 +-
> drivers/net/ethernet/qlogic/qed/qed_debug.c | 415 +++--
> drivers/net/ethernet/qlogic/qed/qed_dev.c | 4 +-
> drivers/net/ethernet/qlogic/qed/qed_hsi.h | 1892 ++++++++++----------
> .../net/ethernet/qlogic/qed/qed_init_fw_funcs.c | 103 +-
> drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 7 -
> drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +-
> drivers/net/ethernet/qlogic/qed/qed_ll2.c | 13 -
> drivers/net/ethernet/qlogic/qede/qede.h | 2 +-
> drivers/scsi/qedf/qedf_version.h | 4 +-
> drivers/scsi/qedi/qedi_version.h | 4 +-
> include/linux/qed/common_hsi.h | 2 +-
> include/linux/qed/eth_common.h | 2 +-
> include/linux/qed/iscsi_common.h | 4 +-
> include/linux/qed/rdma_common.h | 2 +
> include/linux/qed/roce_common.h | 3 +
> 20 files changed, 1319 insertions(+), 1153 deletions(-)
>
> diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
> index db4bf97..7dbbe6d 100644
> +++ b/drivers/infiniband/hw/qedr/main.c
> @@ -51,6 +51,7 @@
> MODULE_DESCRIPTION("QLogic 40G/100G ROCE Driver");
> MODULE_AUTHOR("QLogic Corporation");
> MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_VERSION(QEDR_MODULE_VERSION);
>
> #define QEDR_WQ_MULTIPLIER_DFT (3)
>
> diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h
> index 86d4511..ab0d411 100644
> +++ b/drivers/infiniband/hw/qedr/qedr.h
> @@ -43,6 +43,8 @@
> #include "qedr_hsi_rdma.h"
>
> #define QEDR_NODE_DESC "QLogic 579xx RoCE HCA"
> +#define QEDR_MODULE_VERSION "8.33.11.20"
> +
I thought we had a general prohibition against versions like this in
mainline drivers? And what does this hunk have to do with supporting
new firmware?
Jason
^ permalink raw reply
* [PATCH v3 iproute2-next 0/8] cm_id, cq, mr, and pd resource tracking
From: Steve Wise @ 2018-03-26 20:59 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
Hello,
This series enhances the iproute2 rdma tool to include dumping of
connection manager id (cm_id), completion queue (cq), memory region (mr),
and protection domain (pd) rdma resources. It is the user-space part
of the kernel resource tracking series merged into rdma-next for 4.17 [1].
Changes since v2:
- pull in rdma-core include/rdma/rdma_cma.h
- update the new local rdma/include/uapi/rdma/rdma_netlink.h
- 80 column reformat
- add reviewed-by tags
Changes since v1/RFC:
- removed RFC tag
- initialize rd properly to avoid passing a garbage port number
- revert accidental change to qp_valid_filters
- removed cm_id dev/network/transport types
- cm_id ip addrs now passed up as __kernel_sockaddr_storage
- cm_id ip address ports printed as "address:port" strings
- only parse/display memory keys and iova if available
- filter on "users" for cqs and pds
- fixed memory leaks
- removed PD_FLAGS attribute
- filter on "mrlen" for mrs
- filter on "poll-ctx" for cqs
- don't require addrs or qp_type for parsing cm_ids
- only filter optional attrs if they are present
- remove PGSIZE MR attr to match kernel
[1] https://www.spinics.net/lists/linux-rdma/msg61720.html
---
Steve Wise (8):
rdma: include rdma-core <rdma/rdma_cma.h>
rdma: Makefile change to find <rdma/rdma_cma.h>
rdma: update rdma_netlink.h
rdma: initialize the rd struct
rdma: Add CM_ID resource tracking information
rdma: Add CQ resource tracking information
rdma: Add MR resource tracking information
rdma: Add PD resource tracking information
include/json_writer.h | 2 +
lib/json_writer.c | 11 +
rdma/Makefile | 2 +-
rdma/include/rdma/rdma_cma.h | 728 ++++++++++++++++++++++++++++++++++
rdma/include/uapi/rdma/rdma_netlink.h | 38 ++
rdma/rdma.c | 2 +-
rdma/rdma.h | 2 +
rdma/res.c | 623 ++++++++++++++++++++++++++++-
rdma/utils.c | 16 +
9 files changed, 1421 insertions(+), 3 deletions(-)
create mode 100644 rdma/include/rdma/rdma_cma.h
--
1.8.3.1
^ permalink raw reply
* [PATCH v3 iproute2-next 1/8] rdma: include rdma-core <rdma/rdma_cma.h>
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
This avoids requiring rdma-core be installed on systems.
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
---
rdma/include/rdma/rdma_cma.h | 728 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 728 insertions(+)
create mode 100644 rdma/include/rdma/rdma_cma.h
diff --git a/rdma/include/rdma/rdma_cma.h b/rdma/include/rdma/rdma_cma.h
new file mode 100644
index 0000000..456aa4e
--- /dev/null
+++ b/rdma/include/rdma/rdma_cma.h
@@ -0,0 +1,728 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(_RDMA_CMA_H)
+#define _RDMA_CMA_H
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <infiniband/verbs.h>
+#include <infiniband/sa.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Upon receiving a device removal event, users must destroy the associated
+ * RDMA identifier and release all resources allocated with the device.
+ */
+enum rdma_cm_event_type {
+ RDMA_CM_EVENT_ADDR_RESOLVED,
+ RDMA_CM_EVENT_ADDR_ERROR,
+ RDMA_CM_EVENT_ROUTE_RESOLVED,
+ RDMA_CM_EVENT_ROUTE_ERROR,
+ RDMA_CM_EVENT_CONNECT_REQUEST,
+ RDMA_CM_EVENT_CONNECT_RESPONSE,
+ RDMA_CM_EVENT_CONNECT_ERROR,
+ RDMA_CM_EVENT_UNREACHABLE,
+ RDMA_CM_EVENT_REJECTED,
+ RDMA_CM_EVENT_ESTABLISHED,
+ RDMA_CM_EVENT_DISCONNECTED,
+ RDMA_CM_EVENT_DEVICE_REMOVAL,
+ RDMA_CM_EVENT_MULTICAST_JOIN,
+ RDMA_CM_EVENT_MULTICAST_ERROR,
+ RDMA_CM_EVENT_ADDR_CHANGE,
+ RDMA_CM_EVENT_TIMEWAIT_EXIT
+};
+
+enum rdma_port_space {
+ RDMA_PS_IPOIB = 0x0002,
+ RDMA_PS_TCP = 0x0106,
+ RDMA_PS_UDP = 0x0111,
+ RDMA_PS_IB = 0x013F,
+};
+
+#define RDMA_IB_IP_PS_MASK 0xFFFFFFFFFFFF0000ULL
+#define RDMA_IB_IP_PORT_MASK 0x000000000000FFFFULL
+#define RDMA_IB_IP_PS_TCP 0x0000000001060000ULL
+#define RDMA_IB_IP_PS_UDP 0x0000000001110000ULL
+#define RDMA_IB_PS_IB 0x00000000013F0000ULL
+
+/*
+ * Global qkey value for UDP QPs and multicast groups created via the
+ * RDMA CM.
+ */
+#define RDMA_UDP_QKEY 0x01234567
+
+struct rdma_ib_addr {
+ union ibv_gid sgid;
+ union ibv_gid dgid;
+ __be16 pkey;
+};
+
+struct rdma_addr {
+ union {
+ struct sockaddr src_addr;
+ struct sockaddr_in src_sin;
+ struct sockaddr_in6 src_sin6;
+ struct sockaddr_storage src_storage;
+ };
+ union {
+ struct sockaddr dst_addr;
+ struct sockaddr_in dst_sin;
+ struct sockaddr_in6 dst_sin6;
+ struct sockaddr_storage dst_storage;
+ };
+ union {
+ struct rdma_ib_addr ibaddr;
+ } addr;
+};
+
+struct rdma_route {
+ struct rdma_addr addr;
+ struct ibv_sa_path_rec *path_rec;
+ int num_paths;
+};
+
+struct rdma_event_channel {
+ int fd;
+};
+
+struct rdma_cm_id {
+ struct ibv_context *verbs;
+ struct rdma_event_channel *channel;
+ void *context;
+ struct ibv_qp *qp;
+ struct rdma_route route;
+ enum rdma_port_space ps;
+ uint8_t port_num;
+ struct rdma_cm_event *event;
+ struct ibv_comp_channel *send_cq_channel;
+ struct ibv_cq *send_cq;
+ struct ibv_comp_channel *recv_cq_channel;
+ struct ibv_cq *recv_cq;
+ struct ibv_srq *srq;
+ struct ibv_pd *pd;
+ enum ibv_qp_type qp_type;
+};
+
+enum {
+ RDMA_MAX_RESP_RES = 0xFF,
+ RDMA_MAX_INIT_DEPTH = 0xFF
+};
+
+struct rdma_conn_param {
+ const void *private_data;
+ uint8_t private_data_len;
+ uint8_t responder_resources;
+ uint8_t initiator_depth;
+ uint8_t flow_control;
+ uint8_t retry_count; /* ignored when accepting */
+ uint8_t rnr_retry_count;
+ /* Fields below ignored if a QP is created on the rdma_cm_id. */
+ uint8_t srq;
+ uint32_t qp_num;
+};
+
+struct rdma_ud_param {
+ const void *private_data;
+ uint8_t private_data_len;
+ struct ibv_ah_attr ah_attr;
+ uint32_t qp_num;
+ uint32_t qkey;
+};
+
+struct rdma_cm_event {
+ struct rdma_cm_id *id;
+ struct rdma_cm_id *listen_id;
+ enum rdma_cm_event_type event;
+ int status;
+ union {
+ struct rdma_conn_param conn;
+ struct rdma_ud_param ud;
+ } param;
+};
+
+#define RAI_PASSIVE 0x00000001
+#define RAI_NUMERICHOST 0x00000002
+#define RAI_NOROUTE 0x00000004
+#define RAI_FAMILY 0x00000008
+
+struct rdma_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_qp_type;
+ int ai_port_space;
+ socklen_t ai_src_len;
+ socklen_t ai_dst_len;
+ struct sockaddr *ai_src_addr;
+ struct sockaddr *ai_dst_addr;
+ char *ai_src_canonname;
+ char *ai_dst_canonname;
+ size_t ai_route_len;
+ void *ai_route;
+ size_t ai_connect_len;
+ void *ai_connect;
+ struct rdma_addrinfo *ai_next;
+};
+
+/* Multicast join compatibility mask attributes */
+enum rdma_cm_join_mc_attr_mask {
+ RDMA_CM_JOIN_MC_ATTR_ADDRESS = 1 << 0,
+ RDMA_CM_JOIN_MC_ATTR_JOIN_FLAGS = 1 << 1,
+ RDMA_CM_JOIN_MC_ATTR_RESERVED = 1 << 2,
+};
+
+/* Multicast join flags */
+enum rdma_cm_mc_join_flags {
+ RDMA_MC_JOIN_FLAG_FULLMEMBER,
+ RDMA_MC_JOIN_FLAG_SENDONLY_FULLMEMBER,
+ RDMA_MC_JOIN_FLAG_RESERVED,
+};
+
+struct rdma_cm_join_mc_attr_ex {
+ /* Bitwise OR between "rdma_cm_join_mc_attr_mask" enum */
+ uint32_t comp_mask;
+ /* Use a flag from "rdma_cm_mc_join_flags" enum */
+ uint32_t join_flags;
+ /* Multicast address identifying the group to join */
+ struct sockaddr *addr;
+};
+
+/**
+ * rdma_create_event_channel - Open a channel used to report communication events.
+ * Description:
+ * Asynchronous events are reported to users through event channels. Each
+ * event channel maps to a file descriptor.
+ * Notes:
+ * All created event channels must be destroyed by calling
+ * rdma_destroy_event_channel. Users should call rdma_get_cm_event to
+ * retrieve events on an event channel.
+ * See also:
+ * rdma_get_cm_event, rdma_destroy_event_channel
+ */
+struct rdma_event_channel *rdma_create_event_channel(void);
+
+/**
+ * rdma_destroy_event_channel - Close an event communication channel.
+ * @channel: The communication channel to destroy.
+ * Description:
+ * Release all resources associated with an event channel and closes the
+ * associated file descriptor.
+ * Notes:
+ * All rdma_cm_id's associated with the event channel must be destroyed,
+ * and all returned events must be acked before calling this function.
+ * See also:
+ * rdma_create_event_channel, rdma_get_cm_event, rdma_ack_cm_event
+ */
+void rdma_destroy_event_channel(struct rdma_event_channel *channel);
+
+/**
+ * rdma_create_id - Allocate a communication identifier.
+ * @channel: The communication channel that events associated with the
+ * allocated rdma_cm_id will be reported on.
+ * @id: A reference where the allocated communication identifier will be
+ * returned.
+ * @context: User specified context associated with the rdma_cm_id.
+ * @ps: RDMA port space.
+ * Description:
+ * Creates an identifier that is used to track communication information.
+ * Notes:
+ * Rdma_cm_id's are conceptually equivalent to a socket for RDMA
+ * communication. The difference is that RDMA communication requires
+ * explicitly binding to a specified RDMA device before communication
+ * can occur, and most operations are asynchronous in nature. Communication
+ * events on an rdma_cm_id are reported through the associated event
+ * channel. Users must release the rdma_cm_id by calling rdma_destroy_id.
+ * See also:
+ * rdma_create_event_channel, rdma_destroy_id, rdma_get_devices,
+ * rdma_bind_addr, rdma_resolve_addr, rdma_connect, rdma_listen,
+ */
+int rdma_create_id(struct rdma_event_channel *channel,
+ struct rdma_cm_id **id, void *context,
+ enum rdma_port_space ps);
+
+/**
+ * rdma_create_ep - Allocate a communication identifier and qp.
+ * @id: A reference where the allocated communication identifier will be
+ * returned.
+ * @res: Result from rdma_getaddrinfo, which specifies the source and
+ * destination addresses, plus optional routing and connection information.
+ * @pd: Optional protection domain. This parameter is ignored if qp_init_attr
+ * is NULL.
+ * @qp_init_attr: Optional attributes for a QP created on the rdma_cm_id.
+ * Description:
+ * Create an identifier and option QP used for communication.
+ * Notes:
+ * If qp_init_attr is provided, then a queue pair will be allocated and
+ * associated with the rdma_cm_id. If a pd is provided, the QP will be
+ * created on that PD. Otherwise, the QP will be allocated on a default
+ * PD.
+ * The rdma_cm_id will be set to use synchronous operations (connect,
+ * listen, and get_request). To convert to asynchronous operation, the
+ * rdma_cm_id should be migrated to a user allocated event channel.
+ * See also:
+ * rdma_create_id, rdma_create_qp, rdma_migrate_id, rdma_connect,
+ * rdma_listen
+ */
+int rdma_create_ep(struct rdma_cm_id **id, struct rdma_addrinfo *res,
+ struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr);
+
+/**
+ * rdma_destroy_ep - Deallocates a communication identifier and qp.
+ * @id: The communication identifier to destroy.
+ * Description:
+ * Destroys the specified rdma_cm_id and any associated QP created
+ * on that id.
+ * See also:
+ * rdma_create_ep
+ */
+void rdma_destroy_ep(struct rdma_cm_id *id);
+
+/**
+ * rdma_destroy_id - Release a communication identifier.
+ * @id: The communication identifier to destroy.
+ * Description:
+ * Destroys the specified rdma_cm_id and cancels any outstanding
+ * asynchronous operation.
+ * Notes:
+ * Users must free any associated QP with the rdma_cm_id before
+ * calling this routine and ack an related events.
+ * See also:
+ * rdma_create_id, rdma_destroy_qp, rdma_ack_cm_event
+ */
+int rdma_destroy_id(struct rdma_cm_id *id);
+
+/**
+ * rdma_bind_addr - Bind an RDMA identifier to a source address.
+ * @id: RDMA identifier.
+ * @addr: Local address information. Wildcard values are permitted.
+ * Description:
+ * Associates a source address with an rdma_cm_id. The address may be
+ * wildcarded. If binding to a specific local address, the rdma_cm_id
+ * will also be bound to a local RDMA device.
+ * Notes:
+ * Typically, this routine is called before calling rdma_listen to bind
+ * to a specific port number, but it may also be called on the active side
+ * of a connection before calling rdma_resolve_addr to bind to a specific
+ * address.
+ * See also:
+ * rdma_create_id, rdma_listen, rdma_resolve_addr, rdma_create_qp
+ */
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);
+
+/**
+ * rdma_resolve_addr - Resolve destination and optional source addresses.
+ * @id: RDMA identifier.
+ * @src_addr: Source address information. This parameter may be NULL.
+ * @dst_addr: Destination address information.
+ * @timeout_ms: Time to wait for resolution to complete.
+ * Description:
+ * Resolve destination and optional source addresses from IP addresses
+ * to an RDMA address. If successful, the specified rdma_cm_id will
+ * be bound to a local device.
+ * Notes:
+ * This call is used to map a given destination IP address to a usable RDMA
+ * address. If a source address is given, the rdma_cm_id is bound to that
+ * address, the same as if rdma_bind_addr were called. If no source
+ * address is given, and the rdma_cm_id has not yet been bound to a device,
+ * then the rdma_cm_id will be bound to a source address based on the
+ * local routing tables. After this call, the rdma_cm_id will be bound to
+ * an RDMA device. This call is typically made from the active side of a
+ * connection before calling rdma_resolve_route and rdma_connect.
+ * See also:
+ * rdma_create_id, rdma_resolve_route, rdma_connect, rdma_create_qp,
+ * rdma_get_cm_event, rdma_bind_addr
+ */
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+ struct sockaddr *dst_addr, int timeout_ms);
+
+/**
+ * rdma_resolve_route - Resolve the route information needed to establish a connection.
+ * @id: RDMA identifier.
+ * @timeout_ms: Time to wait for resolution to complete.
+ * Description:
+ * Resolves an RDMA route to the destination address in order to establish
+ * a connection. The destination address must have already been resolved
+ * by calling rdma_resolve_addr.
+ * Notes:
+ * This is called on the client side of a connection after calling
+ * rdma_resolve_addr, but before calling rdma_connect.
+ * See also:
+ * rdma_resolve_addr, rdma_connect, rdma_get_cm_event
+ */
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms);
+
+/**
+ * rdma_create_qp - Allocate a QP.
+ * @id: RDMA identifier.
+ * @pd: Optional protection domain for the QP.
+ * @qp_init_attr: initial QP attributes.
+ * Description:
+ * Allocate a QP associated with the specified rdma_cm_id and transition it
+ * for sending and receiving.
+ * Notes:
+ * The rdma_cm_id must be bound to a local RDMA device before calling this
+ * function, and the protection domain must be for that same device.
+ * QPs allocated to an rdma_cm_id are automatically transitioned by the
+ * librdmacm through their states. After being allocated, the QP will be
+ * ready to handle posting of receives. If the QP is unconnected, it will
+ * be ready to post sends.
+ * If pd is NULL, then the QP will be allocated using a default protection
+ * domain associated with the underlying RDMA device.
+ * See also:
+ * rdma_bind_addr, rdma_resolve_addr, rdma_destroy_qp, ibv_create_qp,
+ * ibv_modify_qp
+ */
+int rdma_create_qp(struct rdma_cm_id *id, struct ibv_pd *pd,
+ struct ibv_qp_init_attr *qp_init_attr);
+int rdma_create_qp_ex(struct rdma_cm_id *id,
+ struct ibv_qp_init_attr_ex *qp_init_attr);
+
+/**
+ * rdma_destroy_qp - Deallocate a QP.
+ * @id: RDMA identifier.
+ * Description:
+ * Destroy a QP allocated on the rdma_cm_id.
+ * Notes:
+ * Users must destroy any QP associated with an rdma_cm_id before
+ * destroying the ID.
+ * See also:
+ * rdma_create_qp, rdma_destroy_id, ibv_destroy_qp
+ */
+void rdma_destroy_qp(struct rdma_cm_id *id);
+
+/**
+ * rdma_connect - Initiate an active connection request.
+ * @id: RDMA identifier.
+ * @conn_param: optional connection parameters.
+ * Description:
+ * For a connected rdma_cm_id, this call initiates a connection request
+ * to a remote destination. For an unconnected rdma_cm_id, it initiates
+ * a lookup of the remote QP providing the datagram service.
+ * Notes:
+ * Users must have resolved a route to the destination address
+ * by having called rdma_resolve_route before calling this routine.
+ * A user may override the default connection parameters and exchange
+ * private data as part of the connection by using the conn_param parameter.
+ * See also:
+ * rdma_resolve_route, rdma_disconnect, rdma_listen, rdma_get_cm_event
+ */
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_listen - Listen for incoming connection requests.
+ * @id: RDMA identifier.
+ * @backlog: backlog of incoming connection requests.
+ * Description:
+ * Initiates a listen for incoming connection requests or datagram service
+ * lookup. The listen will be restricted to the locally bound source
+ * address.
+ * Notes:
+ * Users must have bound the rdma_cm_id to a local address by calling
+ * rdma_bind_addr before calling this routine. If the rdma_cm_id is
+ * bound to a specific IP address, the listen will be restricted to that
+ * address and the associated RDMA device. If the rdma_cm_id is bound
+ * to an RDMA port number only, the listen will occur across all RDMA
+ * devices.
+ * See also:
+ * rdma_bind_addr, rdma_connect, rdma_accept, rdma_reject, rdma_get_cm_event
+ */
+int rdma_listen(struct rdma_cm_id *id, int backlog);
+
+/**
+ * rdma_get_request
+ */
+int rdma_get_request(struct rdma_cm_id *listen, struct rdma_cm_id **id);
+
+/**
+ * rdma_accept - Called to accept a connection request.
+ * @id: Connection identifier associated with the request.
+ * @conn_param: Optional information needed to establish the connection.
+ * Description:
+ * Called from the listening side to accept a connection or datagram
+ * service lookup request.
+ * Notes:
+ * Unlike the socket accept routine, rdma_accept is not called on a
+ * listening rdma_cm_id. Instead, after calling rdma_listen, the user
+ * waits for a connection request event to occur. Connection request
+ * events give the user a newly created rdma_cm_id, similar to a new
+ * socket, but the rdma_cm_id is bound to a specific RDMA device.
+ * rdma_accept is called on the new rdma_cm_id.
+ * A user may override the default connection parameters and exchange
+ * private data as part of the connection by using the conn_param parameter.
+ * See also:
+ * rdma_listen, rdma_reject, rdma_get_cm_event
+ */
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_reject - Called to reject a connection request.
+ * @id: Connection identifier associated with the request.
+ * @private_data: Optional private data to send with the reject message.
+ * @private_data_len: Size of the private_data to send, in bytes.
+ * Description:
+ * Called from the listening side to reject a connection or datagram
+ * service lookup request.
+ * Notes:
+ * After receiving a connection request event, a user may call rdma_reject
+ * to reject the request. If the underlying RDMA transport supports
+ * private data in the reject message, the specified data will be passed to
+ * the remote side.
+ * See also:
+ * rdma_listen, rdma_accept, rdma_get_cm_event
+ */
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+ uint8_t private_data_len);
+
+/**
+ * rdma_notify - Notifies the librdmacm of an asynchronous event.
+ * @id: RDMA identifier.
+ * @event: Asynchronous event.
+ * Description:
+ * Used to notify the librdmacm of asynchronous events that have occurred
+ * on a QP associated with the rdma_cm_id.
+ * Notes:
+ * Asynchronous events that occur on a QP are reported through the user's
+ * device event handler. This routine is used to notify the librdmacm of
+ * communication events. In most cases, use of this routine is not
+ * necessary, however if connection establishment is done out of band
+ * (such as done through Infiniband), it's possible to receive data on a
+ * QP that is not yet considered connected. This routine forces the
+ * connection into an established state in this case in order to handle
+ * the rare situation where the connection never forms on its own.
+ * Events that should be reported to the CM are: IB_EVENT_COMM_EST.
+ * See also:
+ * rdma_connect, rdma_accept, rdma_listen
+ */
+int rdma_notify(struct rdma_cm_id *id, enum ibv_event_type event);
+
+/**
+ * rdma_disconnect - This function disconnects a connection.
+ * @id: RDMA identifier.
+ * Description:
+ * Disconnects a connection and transitions any associated QP to the
+ * error state.
+ * See also:
+ * rdma_connect, rdma_listen, rdma_accept
+ */
+int rdma_disconnect(struct rdma_cm_id *id);
+
+/**
+ * rdma_join_multicast - Joins a multicast group.
+ * @id: Communication identifier associated with the request.
+ * @addr: Multicast address identifying the group to join.
+ * @context: User-defined context associated with the join request.
+ * Description:
+ * Joins a multicast group and attaches an associated QP to the group.
+ * Notes:
+ * Before joining a multicast group, the rdma_cm_id must be bound to
+ * an RDMA device by calling rdma_bind_addr or rdma_resolve_addr. Use of
+ * rdma_resolve_addr requires the local routing tables to resolve the
+ * multicast address to an RDMA device. The user must call
+ * rdma_leave_multicast to leave the multicast group and release any
+ * multicast resources. The context is returned to the user through
+ * the private_data field in the rdma_cm_event.
+ * See also:
+ * rdma_leave_multicast, rdma_bind_addr, rdma_resolve_addr, rdma_create_qp
+ */
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+ void *context);
+
+/**
+ * rdma_leave_multicast - Leaves a multicast group.
+ * @id: Communication identifier associated with the request.
+ * @addr: Multicast address identifying the group to leave.
+ * Description:
+ * Leaves a multicast group and detaches an associated QP from the group.
+ * Notes:
+ * Calling this function before a group has been fully joined results in
+ * canceling the join operation. Users should be aware that messages
+ * received from the multicast group may stilled be queued for
+ * completion processing immediately after leaving a multicast group.
+ * Destroying an rdma_cm_id will automatically leave all multicast groups.
+ * See also:
+ * rdma_join_multicast, rdma_destroy_qp
+ */
+int rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);
+
+/**
+ * rdma_multicast_ex - Joins a multicast group with options.
+ * @id: Communication identifier associated with the request.
+ * @mc_join_attr: Extensive struct containing multicast join parameters.
+ * @context: User-defined context associated with the join request.
+ * Description:
+ * Joins a multicast group with options. Currently supporting MC join flags.
+ * The QP will be attached based on the given join flag.
+ * Join message will be sent according to the join flag.
+ * Notes:
+ * Before joining a multicast group, the rdma_cm_id must be bound to
+ * an RDMA device by calling rdma_bind_addr or rdma_resolve_addr. Use of
+ * rdma_resolve_addr requires the local routing tables to resolve the
+ * multicast address to an RDMA device. The user must call
+ * rdma_leave_multicast to leave the multicast group and release any
+ * multicast resources. The context is returned to the user through
+ * the private_data field in the rdma_cm_event.
+ * See also:
+ * rdma_leave_multicast, rdma_bind_addr, rdma_resolve_addr, rdma_create_qp
+ */
+int rdma_join_multicast_ex(struct rdma_cm_id *id,
+ struct rdma_cm_join_mc_attr_ex *mc_join_attr,
+ void *context);
+
+/**
+ * rdma_get_cm_event - Retrieves the next pending communication event.
+ * @channel: Event channel to check for events.
+ * @event: Allocated information about the next communication event.
+ * Description:
+ * Retrieves a communication event. If no events are pending, by default,
+ * the call will block until an event is received.
+ * Notes:
+ * The default synchronous behavior of this routine can be changed by
+ * modifying the file descriptor associated with the given channel. All
+ * events that are reported must be acknowledged by calling rdma_ack_cm_event.
+ * Destruction of an rdma_cm_id will block until related events have been
+ * acknowledged.
+ * See also:
+ * rdma_ack_cm_event, rdma_create_event_channel, rdma_event_str
+ */
+int rdma_get_cm_event(struct rdma_event_channel *channel,
+ struct rdma_cm_event **event);
+
+/**
+ * rdma_ack_cm_event - Free a communication event.
+ * @event: Event to be released.
+ * Description:
+ * All events which are allocated by rdma_get_cm_event must be released,
+ * there should be a one-to-one correspondence between successful gets
+ * and acks.
+ * See also:
+ * rdma_get_cm_event, rdma_destroy_id
+ */
+int rdma_ack_cm_event(struct rdma_cm_event *event);
+
+__be16 rdma_get_src_port(struct rdma_cm_id *id);
+__be16 rdma_get_dst_port(struct rdma_cm_id *id);
+
+static inline struct sockaddr *rdma_get_local_addr(struct rdma_cm_id *id)
+{
+ return &id->route.addr.src_addr;
+}
+
+static inline struct sockaddr *rdma_get_peer_addr(struct rdma_cm_id *id)
+{
+ return &id->route.addr.dst_addr;
+}
+
+/**
+ * rdma_get_devices - Get list of RDMA devices currently available.
+ * @num_devices: If non-NULL, set to the number of devices returned.
+ * Description:
+ * Return a NULL-terminated array of opened RDMA devices. Callers can use
+ * this routine to allocate resources on specific RDMA devices that will be
+ * shared across multiple rdma_cm_id's.
+ * Notes:
+ * The returned array must be released by calling rdma_free_devices. Devices
+ * remain opened while the librdmacm is loaded.
+ * See also:
+ * rdma_free_devices
+ */
+struct ibv_context **rdma_get_devices(int *num_devices);
+
+/**
+ * rdma_free_devices - Frees the list of devices returned by rdma_get_devices.
+ * @list: List of devices returned from rdma_get_devices.
+ * Description:
+ * Frees the device array returned by rdma_get_devices.
+ * See also:
+ * rdma_get_devices
+ */
+void rdma_free_devices(struct ibv_context **list);
+
+/**
+ * rdma_event_str - Returns a string representation of an rdma cm event.
+ * @event: Asynchronous event.
+ * Description:
+ * Returns a string representation of an asynchronous event.
+ * See also:
+ * rdma_get_cm_event
+ */
+const char *rdma_event_str(enum rdma_cm_event_type event);
+
+/* Option levels */
+enum {
+ RDMA_OPTION_ID = 0,
+ RDMA_OPTION_IB = 1
+};
+
+/* Option details */
+enum {
+ RDMA_OPTION_ID_TOS = 0, /* uint8_t: RFC 2474 */
+ RDMA_OPTION_ID_REUSEADDR = 1, /* int: ~SO_REUSEADDR */
+ RDMA_OPTION_ID_AFONLY = 2, /* int: ~IPV6_V6ONLY */
+ RDMA_OPTION_IB_PATH = 1 /* struct ibv_path_data[] */
+};
+
+/**
+ * rdma_set_option - Set options for an rdma_cm_id.
+ * @id: Communication identifier to set option for.
+ * @level: Protocol level of the option to set.
+ * @optname: Name of the option to set.
+ * @optval: Reference to the option data.
+ * @optlen: The size of the %optval buffer.
+ */
+int rdma_set_option(struct rdma_cm_id *id, int level, int optname,
+ void *optval, size_t optlen);
+
+/**
+ * rdma_migrate_id - Move an rdma_cm_id to a new event channel.
+ * @id: Communication identifier to migrate.
+ * @channel: New event channel for rdma_cm_id events.
+ */
+int rdma_migrate_id(struct rdma_cm_id *id, struct rdma_event_channel *channel);
+
+/**
+ * rdma_getaddrinfo - RDMA address and route resolution service.
+ */
+int rdma_getaddrinfo(const char *node, const char *service,
+ const struct rdma_addrinfo *hints,
+ struct rdma_addrinfo **res);
+
+void rdma_freeaddrinfo(struct rdma_addrinfo *res);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RDMA_CMA_H */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 2/8] rdma: Makefile change to find <rdma/rdma_cma.h>
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
---
rdma/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rdma/Makefile b/rdma/Makefile
index 819fcbe..2cb46b6 100644
--- a/rdma/Makefile
+++ b/rdma/Makefile
@@ -4,7 +4,7 @@ include ../config.mk
TARGETS :=
ifeq ($(HAVE_MNL),y)
-CFLAGS += -I./include/uapi/
+CFLAGS += -I./include/uapi/ -I./include/
RDMA_OBJ = rdma.o utils.o dev.o link.o res.o
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 3/8] rdma: update rdma_netlink.h
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
From: Steve Wise <swise@opengridcomputing.com>
Pull in the latest rdma_netlink.h which has support for
the rdma nldev resource tracking objects being added
with this patch series.
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
---
rdma/include/uapi/rdma/rdma_netlink.h | 38 +++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/rdma/include/uapi/rdma/rdma_netlink.h b/rdma/include/uapi/rdma/rdma_netlink.h
index dbac3b8..9446a72 100644
--- a/rdma/include/uapi/rdma/rdma_netlink.h
+++ b/rdma/include/uapi/rdma/rdma_netlink.h
@@ -238,6 +238,14 @@ enum rdma_nldev_command {
RDMA_NLDEV_CMD_RES_QP_GET, /* can dump */
+ RDMA_NLDEV_CMD_RES_CM_ID_GET, /* can dump */
+
+ RDMA_NLDEV_CMD_RES_CQ_GET, /* can dump */
+
+ RDMA_NLDEV_CMD_RES_MR_GET, /* can dump */
+
+ RDMA_NLDEV_CMD_RES_PD_GET, /* can dump */
+
RDMA_NLDEV_NUM_OPS
};
@@ -350,6 +358,36 @@ enum rdma_nldev_attr {
*/
RDMA_NLDEV_ATTR_RES_KERN_NAME, /* string */
+ RDMA_NLDEV_ATTR_RES_CM_ID, /* nested table */
+ RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY, /* nested table */
+ /*
+ * rdma_cm_id port space.
+ */
+ RDMA_NLDEV_ATTR_RES_PS, /* u32 */
+ /*
+ * Source and destination socket addresses
+ */
+ RDMA_NLDEV_ATTR_RES_SRC_ADDR, /* __kernel_sockaddr_storage */
+ RDMA_NLDEV_ATTR_RES_DST_ADDR, /* __kernel_sockaddr_storage */
+
+ RDMA_NLDEV_ATTR_RES_CQ, /* nested table */
+ RDMA_NLDEV_ATTR_RES_CQ_ENTRY, /* nested table */
+ RDMA_NLDEV_ATTR_RES_CQE, /* u32 */
+ RDMA_NLDEV_ATTR_RES_USECNT, /* u64 */
+ RDMA_NLDEV_ATTR_RES_POLL_CTX, /* u8 */
+
+ RDMA_NLDEV_ATTR_RES_MR, /* nested table */
+ RDMA_NLDEV_ATTR_RES_MR_ENTRY, /* nested table */
+ RDMA_NLDEV_ATTR_RES_RKEY, /* u32 */
+ RDMA_NLDEV_ATTR_RES_LKEY, /* u32 */
+ RDMA_NLDEV_ATTR_RES_IOVA, /* u64 */
+ RDMA_NLDEV_ATTR_RES_MRLEN, /* u64 */
+
+ RDMA_NLDEV_ATTR_RES_PD, /* nested table */
+ RDMA_NLDEV_ATTR_RES_PD_ENTRY, /* nested table */
+ RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY, /* u32 */
+ RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY, /* u32 */
+
RDMA_NLDEV_ATTR_MAX
};
#endif /* _RDMA_NETLINK_H */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 4/8] rdma: initialize the rd struct
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
Initialize the rd struct so port_idx is 0 unless set otherwise.
Otherwise, strict_port queries end up passing an uninitialized PORT
nlattr.
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/rdma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rdma/rdma.c b/rdma/rdma.c
index ab2c960..b43e538 100644
--- a/rdma/rdma.c
+++ b/rdma/rdma.c
@@ -135,7 +135,7 @@ int main(int argc, char **argv)
bool json_output = false;
bool force = false;
char *filename;
- struct rd rd;
+ struct rd rd = {};
int opt;
int err;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 5/8] rdma: Add CM_ID resource tracking information
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
Sample output:
# rdma resource
2: cxgb4_0: pd 5 cq 2 qp 2 cm_id 3 mr 7
3: mlx4_0: pd 7 cq 3 qp 3 cm_id 3 mr 7
# rdma resource show cm_id
link cxgb4_0/- lqpn 0 qp-type RC state LISTEN ps TCP pid 30485 comm rping src-addr 0.0.0.0:7174
link cxgb4_0/2 lqpn 1048 qp-type RC state CONNECT ps TCP pid 30503 comm rping src-addr 172.16.2.1:7174 dst-addr 172.16.2.1:38246
link cxgb4_0/2 lqpn 1040 qp-type RC state CONNECT ps TCP pid 30498 comm rping src-addr 172.16.2.1:38246 dst-addr 172.16.2.1:7174
link mlx4_0/- lqpn 0 qp-type RC state LISTEN ps TCP pid 30485 comm rping src-addr 0.0.0.0:7174
link mlx4_0/1 lqpn 539 qp-type RC state CONNECT ps TCP pid 30494 comm rping src-addr 172.16.99.1:7174 dst-addr 172.16.99.1:43670
link mlx4_0/1 lqpn 538 qp-type RC state CONNECT ps TCP pid 30492 comm rping src-addr 172.16.99.1:43670 dst-addr 172.16.99.1:7174
# rdma resource show cm_id dst-port 7174
link cxgb4_0/2 lqpn 1040 qp-type RC state CONNECT ps TCP pid 30498 comm rping src-addr 172.16.2.1:38246 dst-addr 172.16.2.1:7174
link mlx4_0/1 lqpn 538 qp-type RC state CONNECT ps TCP pid 30492 comm rping src-addr 172.16.99.1:43670 dst-addr 172.16.99.1:7174
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/rdma.h | 2 +
rdma/res.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
rdma/utils.c | 5 ++
3 files changed, 268 insertions(+), 1 deletion(-)
diff --git a/rdma/rdma.h b/rdma/rdma.h
index 5809f70..e55205b 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -18,10 +18,12 @@
#include <libmnl/libmnl.h>
#include <rdma/rdma_netlink.h>
#include <time.h>
+#include <net/if_arp.h>
#include "list.h"
#include "utils.h"
#include "json_writer.h"
+#include <rdma/rdma_cma.h>
#define pr_err(args...) fprintf(stderr, ##args)
#define pr_out(args...) fprintf(stdout, ##args)
diff --git a/rdma/res.c b/rdma/res.c
index 62f5c54..5506cf3 100644
--- a/rdma/res.c
+++ b/rdma/res.c
@@ -16,9 +16,11 @@ static int res_help(struct rd *rd)
{
pr_out("Usage: %s resource\n", rd->filename);
pr_out(" resource show [DEV]\n");
- pr_out(" resource show [qp]\n");
+ pr_out(" resource show [qp|cm_id]\n");
pr_out(" resource show qp link [DEV/PORT]\n");
pr_out(" resource show qp link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
+ pr_out(" resource show cm_id link [DEV/PORT]\n");
+ pr_out(" resource show cm_id link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
return 0;
}
@@ -433,6 +435,245 @@ static int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
+static void print_qp_type(struct rd *rd, uint32_t val)
+{
+ if (rd->json_output)
+ jsonw_string_field(rd->jw, "qp-type",
+ qp_types_to_str(val));
+ else
+ pr_out("qp-type %s ", qp_types_to_str(val));
+}
+
+static const char *cm_id_state_to_str(uint8_t idx)
+{
+ static const char * const cm_id_states_str[] = {
+ "IDLE", "ADDR_QUERY", "ADDR_RESOLVED", "ROUTE_QUERY",
+ "ROUTE_RESOLVED", "CONNECT", "DISCONNECT", "ADDR_BOUND",
+ "LISTEN", "DEVICE_REMOVAL", "DESTROYING" };
+
+ if (idx < ARRAY_SIZE(cm_id_states_str))
+ return cm_id_states_str[idx];
+ return "UNKNOWN";
+}
+
+static const char *cm_id_ps_to_str(uint32_t ps)
+{
+ switch (ps) {
+ case RDMA_PS_IPOIB:
+ return "IPoIB";
+ case RDMA_PS_IB:
+ return "IPoIB";
+ case RDMA_PS_TCP:
+ return "TCP";
+ case RDMA_PS_UDP:
+ return "UDP";
+ default:
+ return "---";
+ }
+}
+
+static void print_cm_id_state(struct rd *rd, uint8_t state)
+{
+ if (rd->json_output) {
+ jsonw_string_field(rd->jw, "state", cm_id_state_to_str(state));
+ return;
+ }
+ pr_out("state %s ", cm_id_state_to_str(state));
+}
+
+static void print_ps(struct rd *rd, uint32_t ps)
+{
+ if (rd->json_output) {
+ jsonw_string_field(rd->jw, "ps", cm_id_ps_to_str(ps));
+ return;
+ }
+ pr_out("ps %s ", cm_id_ps_to_str(ps));
+}
+
+static void print_ipaddr(struct rd *rd, const char *key, char *addrstr,
+ uint16_t port)
+{
+ if (rd->json_output) {
+ int name_size = INET6_ADDRSTRLEN+strlen(":65535");
+ char json_name[name_size];
+
+ snprintf(json_name, name_size, "%s:%u", addrstr, port);
+ jsonw_string_field(rd->jw, key, json_name);
+ return;
+ }
+ pr_out("%s %s:%u ", key, addrstr, port);
+}
+
+static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port)
+{
+ struct __kernel_sockaddr_storage *addr;
+
+ addr = (struct __kernel_sockaddr_storage *)
+ mnl_attr_get_payload(nla_line);
+ switch (addr->ss_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+
+ if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str,
+ INET6_ADDRSTRLEN))
+ return -EINVAL;
+ *port = ntohs(sin->sin_port);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+
+ if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
+ addr_str, INET6_ADDRSTRLEN))
+ return -EINVAL;
+ *port = ntohs(sin6->sin6_port);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+ struct nlattr *nla_table, *nla_entry;
+ struct rd *rd = data;
+ const char *name;
+ int idx;
+
+ mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+ if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
+ !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
+ !tb[RDMA_NLDEV_ATTR_RES_CM_ID])
+ return MNL_CB_ERROR;
+
+ name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+ idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+ nla_table = tb[RDMA_NLDEV_ATTR_RES_CM_ID];
+ mnl_attr_for_each_nested(nla_entry, nla_table) {
+ struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+ char src_addr_str[INET6_ADDRSTRLEN];
+ char dst_addr_str[INET6_ADDRSTRLEN];
+ uint16_t src_port, dst_port;
+ uint32_t port = 0, pid = 0;
+ uint8_t type = 0, state;
+ uint32_t lqpn = 0, ps;
+ char *comm = NULL;
+ int err;
+
+ err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
+ if (err != MNL_CB_OK)
+ return -EINVAL;
+
+ if (!nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
+ !nla_line[RDMA_NLDEV_ATTR_RES_PS] ||
+ (!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
+ !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
+ return MNL_CB_ERROR;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+ port = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
+
+ if (port && port != rd->port_idx)
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN]) {
+ lqpn = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
+ if (rd_check_is_filtered(rd, "lqpn", lqpn))
+ continue;
+ }
+ if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE]) {
+ type = mnl_attr_get_u8(
+ nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
+ if (rd_check_is_string_filtered(rd, "qp-type",
+ qp_types_to_str(type)))
+ continue;
+ }
+
+ ps = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PS]);
+ if (rd_check_is_string_filtered(rd, "ps", cm_id_ps_to_str(ps)))
+ continue;
+
+ state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
+ if (rd_check_is_string_filtered(rd, "state",
+ cm_id_state_to_str(state)))
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]) {
+ if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR],
+ src_addr_str, &src_port))
+ continue;
+ if (rd_check_is_string_filtered(rd, "src-addr",
+ src_addr_str))
+ continue;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]) {
+ if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR],
+ dst_addr_str, &dst_port))
+ continue;
+ if (rd_check_is_string_filtered(rd, "dst-addr",
+ dst_addr_str))
+ continue;
+ }
+
+ if (rd_check_is_filtered(rd, "src-port", src_port))
+ continue;
+
+ if (rd_check_is_filtered(rd, "dst-port", dst_port))
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
+ pid = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_PID]);
+ comm = get_task_name(pid);
+ }
+
+ if (rd_check_is_filtered(rd, "pid", pid)) {
+ free(comm);
+ continue;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) {
+ /* discard const from mnl_attr_get_str */
+ comm = (char *)mnl_attr_get_str(
+ nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
+ }
+
+ if (rd->json_output)
+ jsonw_start_array(rd->jw);
+
+ print_link(rd, idx, name, port, nla_line);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN])
+ print_lqpn(rd, lqpn);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
+ print_qp_type(rd, type);
+ print_cm_id_state(rd, state);
+ print_ps(rd, ps);
+ print_pid(rd, pid);
+ print_comm(rd, comm, nla_line);
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
+ print_ipaddr(rd, "src-addr", src_addr_str, src_port);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
+ print_ipaddr(rd, "dst-addr", dst_addr_str, dst_port);
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+ free(comm);
+
+ if (rd->json_output)
+ jsonw_end_array(rd->jw);
+ else
+ pr_out("\n");
+ }
+ return MNL_CB_OK;
+}
+
RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true);
static const struct
@@ -457,11 +698,30 @@ filters qp_valid_filters[MAX_NUMBER_OF_FILTERS] = {{ .name = "link",
RES_FUNC(res_qp, RDMA_NLDEV_CMD_RES_QP_GET, qp_valid_filters, false);
+static const
+struct filters cm_id_valid_filters[MAX_NUMBER_OF_FILTERS] = {
+ { .name = "link", .is_number = false },
+ { .name = "lqpn", .is_number = true },
+ { .name = "qp-type", .is_number = false },
+ { .name = "state", .is_number = false },
+ { .name = "ps", .is_number = false },
+ { .name = "dev-type", .is_number = false },
+ { .name = "transport-type", .is_number = false },
+ { .name = "pid", .is_number = true },
+ { .name = "src-addr", .is_number = false },
+ { .name = "src-port", .is_number = true },
+ { .name = "dst-addr", .is_number = false },
+ { .name = "dst-port", .is_number = true }
+};
+
+RES_FUNC(res_cm_id, RDMA_NLDEV_CMD_RES_CM_ID_GET, cm_id_valid_filters, false);
+
static int res_show(struct rd *rd)
{
const struct rd_cmd cmds[] = {
{ NULL, res_no_args },
{ "qp", res_qp },
+ { "cm_id", res_cm_id },
{ 0 }
};
diff --git a/rdma/utils.c b/rdma/utils.c
index f946016..ec81737 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -375,6 +375,11 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
[RDMA_NLDEV_ATTR_RES_STATE] = MNL_TYPE_U8,
[RDMA_NLDEV_ATTR_RES_PID] = MNL_TYPE_U32,
[RDMA_NLDEV_ATTR_RES_KERN_NAME] = MNL_TYPE_NUL_STRING,
+ [RDMA_NLDEV_ATTR_RES_CM_ID] = MNL_TYPE_NESTED,
+ [RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY] = MNL_TYPE_NESTED,
+ [RDMA_NLDEV_ATTR_RES_PS] = MNL_TYPE_U32,
+ [RDMA_NLDEV_ATTR_RES_SRC_ADDR] = MNL_TYPE_UNSPEC,
+ [RDMA_NLDEV_ATTR_RES_DST_ADDR] = MNL_TYPE_UNSPEC,
};
int rd_attr_cb(const struct nlattr *attr, void *data)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 6/8] rdma: Add CQ resource tracking information
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
Sample output:
# rdma resource show cq
link cxgb4_0/- cqe 46 users 2 pid 30503 comm rping
link cxgb4_0/- cqe 46 users 2 pid 30498 comm rping
link mlx4_0/- cqe 63 users 2 pid 30494 comm rping
link mlx4_0/- cqe 63 users 2 pid 30489 comm rping
link mlx4_0/- cqe 1023 users 2 poll_ctx WORKQUEUE pid 0 comm [ib_core]
# rdma resource show cq pid 30489
link mlx4_0/- cqe 63 users 2 pid 30489 comm rping
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/res.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rdma/utils.c | 5 +++
2 files changed, 144 insertions(+)
diff --git a/rdma/res.c b/rdma/res.c
index 5506cf3..f1a90d3 100644
--- a/rdma/res.c
+++ b/rdma/res.c
@@ -21,6 +21,8 @@ static int res_help(struct rd *rd)
pr_out(" resource show qp link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
pr_out(" resource show cm_id link [DEV/PORT]\n");
pr_out(" resource show cm_id link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
+ pr_out(" resource show cq link [DEV/PORT]\n");
+ pr_out(" resource show cq link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
return 0;
}
@@ -674,6 +676,132 @@ static int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
+static void print_cqe(struct rd *rd, uint32_t val)
+{
+ if (rd->json_output)
+ jsonw_uint_field(rd->jw, "cqe", val);
+ else
+ pr_out("cqe %u ", val);
+}
+
+static void print_users(struct rd *rd, uint64_t val)
+{
+ if (rd->json_output)
+ jsonw_uint_field(rd->jw, "users", val);
+ else
+ pr_out("users %" PRIu64 " ", val);
+}
+
+static const char *poll_ctx_to_str(uint8_t idx)
+{
+ static const char * const cm_id_states_str[] = {
+ "DIRECT", "SOFTIRQ", "WORKQUEUE"};
+
+ if (idx < ARRAY_SIZE(cm_id_states_str))
+ return cm_id_states_str[idx];
+ return "UNKNOWN";
+}
+
+static void print_poll_ctx(struct rd *rd, uint8_t poll_ctx)
+{
+ if (rd->json_output) {
+ jsonw_string_field(rd->jw, "poll-ctx",
+ poll_ctx_to_str(poll_ctx));
+ return;
+ }
+ pr_out("poll-ctx %s ", poll_ctx_to_str(poll_ctx));
+}
+
+static int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+ struct nlattr *nla_table, *nla_entry;
+ struct rd *rd = data;
+ const char *name;
+ uint32_t idx;
+
+ mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+ if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
+ !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
+ !tb[RDMA_NLDEV_ATTR_RES_CQ])
+ return MNL_CB_ERROR;
+
+ name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+ idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+ nla_table = tb[RDMA_NLDEV_ATTR_RES_CQ];
+
+ mnl_attr_for_each_nested(nla_entry, nla_table) {
+ struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+ char *comm = NULL;
+ uint32_t pid = 0;
+ uint8_t poll_ctx = 0;
+ uint64_t users;
+ uint32_t cqe;
+ int err;
+
+ err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
+ if (err != MNL_CB_OK)
+ return MNL_CB_ERROR;
+
+ if (!nla_line[RDMA_NLDEV_ATTR_RES_CQE] ||
+ !nla_line[RDMA_NLDEV_ATTR_RES_USECNT] ||
+ (!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
+ !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
+ return MNL_CB_ERROR;
+ }
+
+ cqe = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQE]);
+
+ users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
+ if (rd_check_is_filtered(rd, "users", users))
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]) {
+ poll_ctx = mnl_attr_get_u8(
+ nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]);
+ if (rd_check_is_string_filtered(rd, "poll-ctx",
+ poll_ctx_to_str(poll_ctx)))
+ continue;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
+ pid = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_PID]);
+ comm = get_task_name(pid);
+ }
+
+ if (rd_check_is_filtered(rd, "pid", pid)) {
+ free(comm);
+ continue;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
+ /* discard const from mnl_attr_get_str */
+ comm = (char *)mnl_attr_get_str(
+ nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
+
+ if (rd->json_output)
+ jsonw_start_array(rd->jw);
+
+ print_link(rd, idx, name, 0, nla_line);
+ print_cqe(rd, cqe);
+ print_users(rd, users);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX])
+ print_poll_ctx(rd, poll_ctx);
+ print_pid(rd, pid);
+ print_comm(rd, comm, nla_line);
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+ free(comm);
+
+ if (rd->json_output)
+ jsonw_end_array(rd->jw);
+ else
+ pr_out("\n");
+ }
+ return MNL_CB_OK;
+}
+
RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true);
static const struct
@@ -716,12 +844,23 @@ struct filters cm_id_valid_filters[MAX_NUMBER_OF_FILTERS] = {
RES_FUNC(res_cm_id, RDMA_NLDEV_CMD_RES_CM_ID_GET, cm_id_valid_filters, false);
+static const
+struct filters cq_valid_filters[MAX_NUMBER_OF_FILTERS] = {
+ { .name = "link", .is_number = false },
+ { .name = "users", .is_number = true },
+ { .name = "poll-ctx", .is_number = false },
+ { .name = "pid", .is_number = true }
+};
+
+RES_FUNC(res_cq, RDMA_NLDEV_CMD_RES_CQ_GET, cq_valid_filters, true);
+
static int res_show(struct rd *rd)
{
const struct rd_cmd cmds[] = {
{ NULL, res_no_args },
{ "qp", res_qp },
{ "cm_id", res_cm_id },
+ { "cq", res_cq },
{ 0 }
};
diff --git a/rdma/utils.c b/rdma/utils.c
index ec81737..5e79b62 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -380,6 +380,11 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
[RDMA_NLDEV_ATTR_RES_PS] = MNL_TYPE_U32,
[RDMA_NLDEV_ATTR_RES_SRC_ADDR] = MNL_TYPE_UNSPEC,
[RDMA_NLDEV_ATTR_RES_DST_ADDR] = MNL_TYPE_UNSPEC,
+ [RDMA_NLDEV_ATTR_RES_CQ] = MNL_TYPE_NESTED,
+ [RDMA_NLDEV_ATTR_RES_CQ_ENTRY] = MNL_TYPE_NESTED,
+ [RDMA_NLDEV_ATTR_RES_CQE] = MNL_TYPE_U32,
+ [RDMA_NLDEV_ATTR_RES_USECNT] = MNL_TYPE_U64,
+ [RDMA_NLDEV_ATTR_RES_POLL_CTX] = MNL_TYPE_U8,
};
int rd_attr_cb(const struct nlattr *attr, void *data)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 7/8] rdma: Add MR resource tracking information
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
Sample output:
Without CAP_NET_ADMIN:
$ rdma resource show mr mrlen 65536
link mlx4_0/- mrlen 65536 pid 0 comm [nvme_rdma]
link cxgb4_0/- mrlen 65536 pid 0 comm [nvme_rdma]
With CAP_NET_ADMIN:
# rdma resource show mr mrlen 65536
link mlx4_0/- rkey 0x12702 lkey 0x12702 iova 0x85724a000 mrlen 65536 pid 0 comm [nvme_rdma]
link cxgb4_0/- rkey 0x68fe4e9 lkey 0x68fe4e9 iova 0x835b91000 mrlen 65536 pid 0 comm [nvme_rdma]
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
include/json_writer.h | 2 +
lib/json_writer.c | 11 +++++
rdma/res.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++
rdma/utils.c | 6 +++
4 files changed, 146 insertions(+)
diff --git a/include/json_writer.h b/include/json_writer.h
index 45459fa..4b4dec2 100644
--- a/include/json_writer.h
+++ b/include/json_writer.h
@@ -35,6 +35,7 @@ void jsonw_bool(json_writer_t *self, bool value);
void jsonw_float(json_writer_t *self, double number);
void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num);
void jsonw_uint(json_writer_t *self, uint64_t number);
+void jsonw_xint(json_writer_t *self, uint64_t number);
void jsonw_hu(json_writer_t *self, unsigned short number);
void jsonw_int(json_writer_t *self, int64_t number);
void jsonw_null(json_writer_t *self);
@@ -45,6 +46,7 @@ void jsonw_string_field(json_writer_t *self, const char *prop, const char *val);
void jsonw_bool_field(json_writer_t *self, const char *prop, bool value);
void jsonw_float_field(json_writer_t *self, const char *prop, double num);
void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num);
+void jsonw_xint_field(json_writer_t *self, const char *prop, uint64_t num);
void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num);
void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num);
void jsonw_null_field(json_writer_t *self, const char *prop);
diff --git a/lib/json_writer.c b/lib/json_writer.c
index 68401ae..0ad0421 100644
--- a/lib/json_writer.c
+++ b/lib/json_writer.c
@@ -225,6 +225,11 @@ void jsonw_uint(json_writer_t *self, uint64_t num)
jsonw_printf(self, "%"PRIu64, num);
}
+void jsonw_xint(json_writer_t *self, uint64_t num)
+{
+ jsonw_printf(self, "%"PRIx64, num);
+}
+
void jsonw_lluint(json_writer_t *self, unsigned long long int num)
{
jsonw_printf(self, "%llu", num);
@@ -269,6 +274,12 @@ void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
jsonw_uint(self, num);
}
+void jsonw_xint_field(json_writer_t *self, const char *prop, uint64_t num)
+{
+ jsonw_name(self, prop);
+ jsonw_xint(self, num);
+}
+
void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
{
jsonw_name(self, prop);
diff --git a/rdma/res.c b/rdma/res.c
index f1a90d3..aa61e73 100644
--- a/rdma/res.c
+++ b/rdma/res.c
@@ -802,6 +802,121 @@ static int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
+static void print_key(struct rd *rd, const char *name, uint32_t val)
+{
+ if (rd->json_output)
+ jsonw_xint_field(rd->jw, name, val);
+ else
+ pr_out("%s 0x%x ", name, val);
+}
+
+static void print_iova(struct rd *rd, uint64_t val)
+{
+ if (rd->json_output)
+ jsonw_xint_field(rd->jw, "iova", val);
+ else
+ pr_out("iova 0x%" PRIx64 " ", val);
+}
+
+static void print_mrlen(struct rd *rd, uint64_t val)
+{
+ if (rd->json_output)
+ jsonw_uint_field(rd->jw, "mrlen", val);
+ else
+ pr_out("mrlen %" PRIu64 " ", val);
+}
+
+static int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+ struct nlattr *nla_table, *nla_entry;
+ struct rd *rd = data;
+ const char *name;
+ uint32_t idx;
+
+ mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+ if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
+ !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
+ !tb[RDMA_NLDEV_ATTR_RES_MR])
+ return MNL_CB_ERROR;
+
+ name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+ idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+ nla_table = tb[RDMA_NLDEV_ATTR_RES_MR];
+
+ mnl_attr_for_each_nested(nla_entry, nla_table) {
+ struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+ uint32_t rkey = 0, lkey = 0;
+ uint64_t iova = 0, mrlen;
+ char *comm = NULL;
+ uint32_t pid = 0;
+ int err;
+
+ err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
+ if (err != MNL_CB_OK)
+ return MNL_CB_ERROR;
+
+ if (!nla_line[RDMA_NLDEV_ATTR_RES_MRLEN] ||
+ (!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
+ !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
+ return MNL_CB_ERROR;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_RKEY])
+ rkey = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_RKEY]);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_LKEY])
+ lkey = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_LKEY]);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_IOVA])
+ iova = mnl_attr_get_u64(
+ nla_line[RDMA_NLDEV_ATTR_RES_IOVA]);
+
+ mrlen = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]);
+ if (rd_check_is_filtered(rd, "mrlen", mrlen))
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
+ pid = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_PID]);
+ comm = get_task_name(pid);
+ }
+
+ if (rd_check_is_filtered(rd, "pid", pid)) {
+ free(comm);
+ continue;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
+ /* discard const from mnl_attr_get_str */
+ comm = (char *)mnl_attr_get_str(
+ nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
+
+ if (rd->json_output)
+ jsonw_start_array(rd->jw);
+
+ print_link(rd, idx, name, 0, nla_line);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_RKEY])
+ print_key(rd, "rkey", rkey);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_LKEY])
+ print_key(rd, "lkey", lkey);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_IOVA])
+ print_iova(rd, iova);
+ print_mrlen(rd, mrlen);
+ print_pid(rd, pid);
+ print_comm(rd, comm, nla_line);
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+ free(comm);
+
+ if (rd->json_output)
+ jsonw_end_array(rd->jw);
+ else
+ pr_out("\n");
+ }
+ return MNL_CB_OK;
+}
+
RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true);
static const struct
@@ -854,6 +969,17 @@ struct filters cq_valid_filters[MAX_NUMBER_OF_FILTERS] = {
RES_FUNC(res_cq, RDMA_NLDEV_CMD_RES_CQ_GET, cq_valid_filters, true);
+static const
+struct filters mr_valid_filters[MAX_NUMBER_OF_FILTERS] = {
+ { .name = "link", .is_number = false },
+ { .name = "rkey", .is_number = true },
+ { .name = "lkey", .is_number = true },
+ { .name = "mrlen", .is_number = true },
+ { .name = "pid", .is_number = true }
+};
+
+RES_FUNC(res_mr, RDMA_NLDEV_CMD_RES_MR_GET, mr_valid_filters, true);
+
static int res_show(struct rd *rd)
{
const struct rd_cmd cmds[] = {
@@ -861,6 +987,7 @@ static int res_show(struct rd *rd)
{ "qp", res_qp },
{ "cm_id", res_cm_id },
{ "cq", res_cq },
+ { "mr", res_mr },
{ 0 }
};
diff --git a/rdma/utils.c b/rdma/utils.c
index 5e79b62..a2e08e9 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -385,6 +385,12 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
[RDMA_NLDEV_ATTR_RES_CQE] = MNL_TYPE_U32,
[RDMA_NLDEV_ATTR_RES_USECNT] = MNL_TYPE_U64,
[RDMA_NLDEV_ATTR_RES_POLL_CTX] = MNL_TYPE_U8,
+ [RDMA_NLDEV_ATTR_RES_MR] = MNL_TYPE_NESTED,
+ [RDMA_NLDEV_ATTR_RES_MR_ENTRY] = MNL_TYPE_NESTED,
+ [RDMA_NLDEV_ATTR_RES_RKEY] = MNL_TYPE_U32,
+ [RDMA_NLDEV_ATTR_RES_LKEY] = MNL_TYPE_U32,
+ [RDMA_NLDEV_ATTR_RES_IOVA] = MNL_TYPE_U64,
+ [RDMA_NLDEV_ATTR_RES_MRLEN] = MNL_TYPE_U64,
};
int rd_attr_cb(const struct nlattr *attr, void *data)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 iproute2-next 8/8] rdma: Add PD resource tracking information
From: Steve Wise @ 2018-03-26 20:57 UTC (permalink / raw)
To: dsahern; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522097991.git.swise@opengridcomputing.com>
Sample output:
Without CAP_NET_ADMIN capability:
link mlx4_0/- users 0 pid 0 comm [ib_srpt]
link mlx4_0/- users 0 pid 0 comm [ib_srp]
link mlx4_0/- users 1 pid 0 comm [ib_core]
link cxgb4_0/- users 0 pid 0 comm [ib_srp]
With CAP_NET_ADMIN capability:
link mlx4_0/- local_dma_lkey 0x8000 users 0 pid 0 comm [ib_srpt]
link mlx4_0/- local_dma_lkey 0x8000 users 0 pid 0 comm [ib_srp]
link mlx4_0/- local_dma_lkey 0x8000 users 1 pid 0 comm [ib_core]
link cxgb4_0/- local_dma_lkey 0x0 users 0 pid 0 comm [ib_srp]
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/res.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/rdma/res.c b/rdma/res.c
index aa61e73..6177e46 100644
--- a/rdma/res.c
+++ b/rdma/res.c
@@ -917,6 +917,91 @@ static int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
+static int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+ struct nlattr *nla_table, *nla_entry;
+ struct rd *rd = data;
+ const char *name;
+ uint32_t idx;
+
+ mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+ if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
+ !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
+ !tb[RDMA_NLDEV_ATTR_RES_PD])
+ return MNL_CB_ERROR;
+
+ name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+ idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+ nla_table = tb[RDMA_NLDEV_ATTR_RES_PD];
+
+ mnl_attr_for_each_nested(nla_entry, nla_table) {
+ uint32_t local_dma_lkey = 0, unsafe_global_rkey = 0;
+ struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+ char *comm = NULL;
+ uint32_t pid = 0;
+ uint64_t users;
+ int err;
+
+ err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
+ if (err != MNL_CB_OK)
+ return MNL_CB_ERROR;
+
+ if (!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] ||
+ (!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
+ !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
+ return MNL_CB_ERROR;
+ }
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY])
+ local_dma_lkey = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]);
+
+ users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
+ if (rd_check_is_filtered(rd, "users", users))
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY])
+ unsafe_global_rkey = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]);
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
+ pid = mnl_attr_get_u32(
+ nla_line[RDMA_NLDEV_ATTR_RES_PID]);
+ comm = get_task_name(pid);
+ }
+
+ if (rd_check_is_filtered(rd, "pid", pid))
+ continue;
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
+ /* discard const from mnl_attr_get_str */
+ comm = (char *)mnl_attr_get_str(
+ nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
+
+ if (rd->json_output)
+ jsonw_start_array(rd->jw);
+
+ print_link(rd, idx, name, 0, nla_line);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY])
+ print_key(rd, "local_dma_lkey", local_dma_lkey);
+ print_users(rd, users);
+ if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY])
+ print_key(rd, "unsafe_global_rkey", unsafe_global_rkey);
+ print_pid(rd, pid);
+ print_comm(rd, comm, nla_line);
+
+ if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+ free(comm);
+
+ if (rd->json_output)
+ jsonw_end_array(rd->jw);
+ else
+ pr_out("\n");
+ }
+ return MNL_CB_OK;
+}
+
RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true);
static const struct
@@ -980,6 +1065,15 @@ struct filters mr_valid_filters[MAX_NUMBER_OF_FILTERS] = {
RES_FUNC(res_mr, RDMA_NLDEV_CMD_RES_MR_GET, mr_valid_filters, true);
+static const
+struct filters pd_valid_filters[MAX_NUMBER_OF_FILTERS] = {
+ { .name = "link", .is_number = false },
+ { .name = "users", .is_number = true },
+ { .name = "pid", .is_number = true }
+};
+
+RES_FUNC(res_pd, RDMA_NLDEV_CMD_RES_PD_GET, pd_valid_filters, true);
+
static int res_show(struct rd *rd)
{
const struct rd_cmd cmds[] = {
@@ -988,6 +1082,7 @@ static int res_show(struct rd *rd)
{ "cm_id", res_cm_id },
{ "cq", res_cq },
{ "mr", res_mr },
+ { "pd", res_pd },
{ 0 }
};
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH net-next 1/2] net: systemport: Implement adaptive interrupt coalescing
From: Tal Gilboa @ 2018-03-26 21:22 UTC (permalink / raw)
To: Florian Fainelli, netdev
Cc: davem, jaedon.shin, pgynther, opendmb, michal.chan, gospo, saeedm
In-Reply-To: <20180323011933.29748-2-f.fainelli@gmail.com>
On 3/23/2018 4:19 AM, Florian Fainelli wrote:
> Implement support for adaptive RX and TX interrupt coalescing using
> net_dim. We have each of our TX ring and our single RX ring implement a
> bcm_sysport_net_dim structure which holds an interrupt counter, number
> of packets, bytes, and a container for a net_dim instance.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> drivers/net/ethernet/broadcom/bcmsysport.c | 141 ++++++++++++++++++++++++++---
> drivers/net/ethernet/broadcom/bcmsysport.h | 14 +++
> 2 files changed, 140 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
> index f15a8fc6dfc9..5a5a726bafa4 100644
> --- a/drivers/net/ethernet/broadcom/bcmsysport.c
> +++ b/drivers/net/ethernet/broadcom/bcmsysport.c
> @@ -15,6 +15,7 @@
> #include <linux/module.h>
> #include <linux/kernel.h>
> #include <linux/netdevice.h>
> +#include <linux/net_dim.h>
I don't think you need this include. You already include net_dim in
bcmsysport.h and include the bcmsysport.h here.
> #include <linux/etherdevice.h>
> #include <linux/platform_device.h>
> #include <linux/of.h>
> @@ -574,21 +575,55 @@ static int bcm_sysport_set_wol(struct net_device *dev,
> return 0;
> }
>
> +static void bcm_sysport_set_rx_coalesce(struct bcm_sysport_priv *priv)
> +{
> + u32 reg;
> +
> + reg = rdma_readl(priv, RDMA_MBDONE_INTR);
> + reg &= ~(RDMA_INTR_THRESH_MASK |
> + RDMA_TIMEOUT_MASK << RDMA_TIMEOUT_SHIFT);
> + reg |= priv->dim.coal_pkts;
> + reg |= DIV_ROUND_UP(priv->dim.coal_usecs * 1000, 8192) <<
> + RDMA_TIMEOUT_SHIFT;
> + rdma_writel(priv, reg, RDMA_MBDONE_INTR);
> +}
> +
> +static void bcm_sysport_set_tx_coalesce(struct bcm_sysport_tx_ring *ring)
> +{
> + struct bcm_sysport_priv *priv = ring->priv;
> + u32 reg;
> +
> + reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(ring->index));
> + reg &= ~(RING_INTR_THRESH_MASK |
> + RING_TIMEOUT_MASK << RING_TIMEOUT_SHIFT);
> + reg |= ring->dim.coal_pkts;
> + reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192) <<
> + RING_TIMEOUT_SHIFT;
> + tdma_writel(priv, reg, TDMA_DESC_RING_INTR_CONTROL(ring->index));
> +}
> +
I wouldn't couple these functions with dim. This implies dim is always
used. IMO, would be more clear to use a generic method which takes usecs
and packets as an argument.
> static int bcm_sysport_get_coalesce(struct net_device *dev,
> struct ethtool_coalesce *ec)
> {
> struct bcm_sysport_priv *priv = netdev_priv(dev);
> + struct bcm_sysport_tx_ring *ring;
> + unsigned int i;
> u32 reg;
>
> reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(0));
>
> ec->tx_coalesce_usecs = (reg >> RING_TIMEOUT_SHIFT) * 8192 / 1000;
> ec->tx_max_coalesced_frames = reg & RING_INTR_THRESH_MASK;
> + for (i = 0; i < dev->num_tx_queues; i++) {
> + ring = &priv->tx_rings[i];
> + ec->use_adaptive_tx_coalesce |= ring->dim.use_dim;
> + }
>
> reg = rdma_readl(priv, RDMA_MBDONE_INTR);
>
> ec->rx_coalesce_usecs = (reg >> RDMA_TIMEOUT_SHIFT) * 8192 / 1000;
> ec->rx_max_coalesced_frames = reg & RDMA_INTR_THRESH_MASK;
> + ec->use_adaptive_rx_coalesce = priv->dim.use_dim;
>
> return 0;
> }
> @@ -597,8 +632,8 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
> struct ethtool_coalesce *ec)
> {
> struct bcm_sysport_priv *priv = netdev_priv(dev);
> + struct bcm_sysport_tx_ring *ring;
> unsigned int i;
> - u32 reg;
>
> /* Base system clock is 125Mhz, DMA timeout is this reference clock
> * divided by 1024, which yield roughly 8.192 us, our maximum value has
> @@ -615,22 +650,26 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
> return -EINVAL;
>
> for (i = 0; i < dev->num_tx_queues; i++) {
> - reg = tdma_readl(priv, TDMA_DESC_RING_INTR_CONTROL(i));
> - reg &= ~(RING_INTR_THRESH_MASK |
> - RING_TIMEOUT_MASK << RING_TIMEOUT_SHIFT);
> - reg |= ec->tx_max_coalesced_frames;
> - reg |= DIV_ROUND_UP(ec->tx_coalesce_usecs * 1000, 8192) <<
> - RING_TIMEOUT_SHIFT;
> - tdma_writel(priv, reg, TDMA_DESC_RING_INTR_CONTROL(i));
> + ring = &priv->tx_rings[i];
> + ring->dim.coal_pkts = ec->tx_max_coalesced_frames;
> + ring->dim.coal_usecs = ec->tx_coalesce_usecs;
> + if (!ec->use_adaptive_tx_coalesce && ring->dim.use_dim) {
> + ring->dim.coal_pkts = 1;
> + ring->dim.coal_usecs = 0;
> + }
> + ring->dim.use_dim = ec->use_adaptive_tx_coalesce;
> + bcm_sysport_set_tx_coalesce(ring);
> }
If I understand correctly, if I disable dim, moderation is set to
{usecs,packets}={0,1} regardless of the input from ethtool right?
Doesn't this break the wanted behavior? As mentioned above, I would
decouple dim from the set_tx/rx_coalesce() function. Also, when dim is
enabled, why change dim.coal_pkts/usecs? They would just be overwritten
in the next iteration of net_dim.
>
> - reg = rdma_readl(priv, RDMA_MBDONE_INTR);
> - reg &= ~(RDMA_INTR_THRESH_MASK |
> - RDMA_TIMEOUT_MASK << RDMA_TIMEOUT_SHIFT);
> - reg |= ec->rx_max_coalesced_frames;
> - reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192) <<
> - RDMA_TIMEOUT_SHIFT;
> - rdma_writel(priv, reg, RDMA_MBDONE_INTR);
> + priv->dim.coal_usecs = ec->rx_coalesce_usecs;
> + priv->dim.coal_pkts = ec->rx_max_coalesced_frames;
> +
> + if (!ec->use_adaptive_rx_coalesce && priv->dim.use_dim) {
> + priv->dim.coal_pkts = 1;
> + priv->dim.coal_usecs = 0;
> + }
> + priv->dim.use_dim = ec->use_adaptive_rx_coalesce;
> + bcm_sysport_set_rx_coalesce(priv);
Same comment as above.
>
> return 0;
> }
> @@ -709,6 +748,7 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
> struct bcm_sysport_stats64 *stats64 = &priv->stats64;
> struct net_device *ndev = priv->netdev;
> unsigned int processed = 0, to_process;
> + unsigned int processed_bytes = 0;
> struct bcm_sysport_cb *cb;
> struct sk_buff *skb;
> unsigned int p_index;
> @@ -800,6 +840,7 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
> */
> skb_pull(skb, sizeof(*rsb) + 2);
> len -= (sizeof(*rsb) + 2);
> + processed_bytes += len;
>
> /* UniMAC may forward CRC */
> if (priv->crc_fwd) {
> @@ -824,6 +865,9 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
> priv->rx_read_ptr = 0;
> }
>
> + priv->dim.packets = processed;
> + priv->dim.bytes = processed_bytes;
> +
> return processed;
> }
>
> @@ -900,6 +944,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
> ring->packets += pkts_compl;
> ring->bytes += bytes_compl;
> u64_stats_update_end(&priv->syncp);
> + ring->dim.packets = pkts_compl;
> + ring->dim.bytes = bytes_compl;
>
> ring->c_index = c_index;
>
> @@ -945,6 +991,7 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
> {
> struct bcm_sysport_tx_ring *ring =
> container_of(napi, struct bcm_sysport_tx_ring, napi);
> + struct net_dim_sample dim_sample;
> unsigned int work_done = 0;
>
> work_done = bcm_sysport_tx_reclaim(ring->priv, ring);
> @@ -961,6 +1008,12 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
> return 0;
> }
>
> + if (ring->dim.use_dim) {
> + net_dim_sample(ring->dim.event_ctr, ring->dim.packets,
> + ring->dim.bytes, &dim_sample);
> + net_dim(&ring->dim.dim, dim_sample);
> + }
> +
> return budget;
> }
>
> @@ -976,6 +1029,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
> {
> struct bcm_sysport_priv *priv =
> container_of(napi, struct bcm_sysport_priv, napi);
> + struct net_dim_sample dim_sample;
> unsigned int work_done = 0;
>
> work_done = bcm_sysport_desc_rx(priv, budget);
> @@ -998,6 +1052,12 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
> intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE);
> }
>
> + if (priv->dim.use_dim) {
> + net_dim_sample(priv->dim.event_ctr, priv->dim.packets,
> + priv->dim.bytes, &dim_sample);
> + net_dim(&priv->dim.dim, dim_sample);
> + }
> +
> return work_done;
> }
>
> @@ -1016,6 +1076,40 @@ static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
> netif_dbg(priv, wol, priv->netdev, "resumed from WOL\n");
> }
>
> +static void bcm_sysport_dim_work(struct work_struct *work)
> +{
> + struct net_dim *dim = container_of(work, struct net_dim, work);
> + struct bcm_sysport_net_dim *ndim =
> + container_of(dim, struct bcm_sysport_net_dim, dim);
> + struct bcm_sysport_priv *priv =
> + container_of(ndim, struct bcm_sysport_priv, dim);
> + struct net_dim_cq_moder cur_profile =
> + net_dim_get_profile(dim->mode, dim->profile_ix);
> +
> + priv->dim.coal_usecs = cur_profile.usec;
> + priv->dim.coal_pkts = cur_profile.pkts;
> +
> + bcm_sysport_set_rx_coalesce(priv);
> + dim->state = NET_DIM_START_MEASURE;
> +}
> +
> +static void bcm_sysport_dim_tx_work(struct work_struct *work)
> +{
> + struct net_dim *dim = container_of(work, struct net_dim, work);
> + struct bcm_sysport_net_dim *ndim =
> + container_of(dim, struct bcm_sysport_net_dim, dim);
> + struct bcm_sysport_tx_ring *ring =
> + container_of(ndim, struct bcm_sysport_tx_ring, dim);
> + struct net_dim_cq_moder cur_profile =
> + net_dim_get_profile(dim->mode, dim->profile_ix);
> +
> + ring->dim.coal_usecs = cur_profile.usec;
> + ring->dim.coal_pkts = cur_profile.pkts;
> +
> + bcm_sysport_set_tx_coalesce(ring);
> + dim->state = NET_DIM_START_MEASURE;
> +}
> +
> /* RX and misc interrupt routine */
> static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
> {
> @@ -1034,6 +1128,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
> }
>
> if (priv->irq0_stat & INTRL2_0_RDMA_MBDONE) {
> + priv->dim.event_ctr++;
> if (likely(napi_schedule_prep(&priv->napi))) {
> /* disable RX interrupts */
> intrl2_0_mask_set(priv, INTRL2_0_RDMA_MBDONE);
> @@ -1061,6 +1156,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
> continue;
>
> txr = &priv->tx_rings[ring];
> + txr->dim.event_ctr++;
>
> if (likely(napi_schedule_prep(&txr->napi))) {
> intrl2_0_mask_set(priv, ring_bit);
> @@ -1093,6 +1189,7 @@ static irqreturn_t bcm_sysport_tx_isr(int irq, void *dev_id)
> continue;
>
> txr = &priv->tx_rings[ring];
> + txr->dim.event_ctr++;
>
> if (likely(napi_schedule_prep(&txr->napi))) {
> intrl2_1_mask_set(priv, BIT(ring));
> @@ -1358,6 +1455,16 @@ static void bcm_sysport_adj_link(struct net_device *dev)
> phy_print_status(phydev);
> }
>
> +static void bcm_sysport_init_dim(struct bcm_sysport_net_dim *dim,
> + void (*cb)(struct work_struct *work))
> +{
> + INIT_WORK(&dim->dim.work, cb);
> + dim->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
> + dim->event_ctr = 0;
> + dim->packets = 0;
> + dim->bytes = 0;
> +}
What about default values for coal_usecs/pkts? dim supports it through
net_dim_get_def_profile(mode) function.
> +
> static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
> unsigned int index)
> {
> @@ -1447,6 +1554,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
> reg |= (1 << index);
> tdma_writel(priv, reg, TDMA_TIER1_ARB_0_QUEUE_EN);
>
> + bcm_sysport_init_dim(&ring->dim, bcm_sysport_dim_tx_work);
> napi_enable(&ring->napi);
>
> netif_dbg(priv, hw, priv->netdev,
> @@ -1477,6 +1585,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
> return;
>
> napi_disable(&ring->napi);
> + cancel_work_sync(&ring->dim.dim.work);
> netif_napi_del(&ring->napi);
>
> bcm_sysport_tx_clean(priv, ring);
> @@ -1766,6 +1875,7 @@ static void bcm_sysport_netif_start(struct net_device *dev)
> struct bcm_sysport_priv *priv = netdev_priv(dev);
>
> /* Enable NAPI */
> + bcm_sysport_init_dim(&priv->dim, bcm_sysport_dim_work);
> napi_enable(&priv->napi);
>
> /* Enable RX interrupt and TX ring full interrupt */
> @@ -1951,6 +2061,7 @@ static void bcm_sysport_netif_stop(struct net_device *dev)
> /* stop all software from updating hardware */
> netif_tx_stop_all_queues(dev);
> napi_disable(&priv->napi);
> + cancel_work_sync(&priv->dim.dim.work);
> phy_stop(dev->phydev);
>
> /* mask all interrupts */
> diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
> index f5a984c1c986..9f48ad3cc38d 100644
> --- a/drivers/net/ethernet/broadcom/bcmsysport.h
> +++ b/drivers/net/ethernet/broadcom/bcmsysport.h
> @@ -12,6 +12,7 @@
> #define __BCM_SYSPORT_H
>
> #include <linux/if_vlan.h>
> +#include <linux/net_dim.h>
>
> /* Receive/transmit descriptor format */
> #define DESC_ADDR_HI_STATUS_LEN 0x00
> @@ -695,6 +696,16 @@ struct bcm_sysport_hw_params {
> unsigned int num_rx_desc_words;
> };
>
> +struct bcm_sysport_net_dim {
> + u16 use_dim;
> + u16 event_ctr;
> + unsigned long packets;
> + unsigned long bytes;
> + u32 coal_usecs;
> + u32 coal_pkts;
> + struct net_dim dim;
> +};
> +
> /* Software view of the TX ring */
> struct bcm_sysport_tx_ring {
> spinlock_t lock; /* Ring lock for tx reclaim/xmit */
> @@ -712,6 +723,7 @@ struct bcm_sysport_tx_ring {
> struct bcm_sysport_priv *priv; /* private context backpointer */
> unsigned long packets; /* packets statistics */
> unsigned long bytes; /* bytes statistics */
> + struct bcm_sysport_net_dim dim; /* Net DIM context */
> unsigned int switch_queue; /* switch port queue number */
> unsigned int switch_port; /* switch port queue number */
> bool inspect; /* inspect switch port and queue */
> @@ -743,6 +755,8 @@ struct bcm_sysport_priv {
> unsigned int rx_read_ptr;
> unsigned int rx_c_index;
>
> + struct bcm_sysport_net_dim dim;
> +
> /* PHY device */
> struct device_node *phy_dn;
> phy_interface_t phy_interface;
>
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: bcmgenet: Add support for adaptive RX coalescing
From: Tal Gilboa @ 2018-03-26 21:23 UTC (permalink / raw)
To: Florian Fainelli, netdev
Cc: davem, jaedon.shin, pgynther, opendmb, michal.chan, gospo, saeedm
In-Reply-To: <20180323011933.29748-3-f.fainelli@gmail.com>
On 3/23/2018 4:19 AM, Florian Fainelli wrote:
> Unlike the moder modern SYSTEMPORT hardware, we do not have a
> configurable TDMA timeout, which limits us to implement adaptive RX
> interrupt coalescing only. We have each of our RX rings implement a
> bcmgenet_net_dim structure which holds an interrupt counter, number of
> packets, bytes, and a container for a net_dim instance.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> drivers/net/ethernet/broadcom/genet/bcmgenet.c | 109 +++++++++++++++++++++----
> drivers/net/ethernet/broadcom/genet/bcmgenet.h | 12 +++
> 2 files changed, 103 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index b1e35a9accf1..7db8edc643ec 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -603,6 +603,8 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
> struct ethtool_coalesce *ec)
> {
> struct bcmgenet_priv *priv = netdev_priv(dev);
> + struct bcmgenet_rx_ring *ring;
> + unsigned int i;
>
> ec->tx_max_coalesced_frames =
> bcmgenet_tdma_ring_readl(priv, DESC_INDEX,
> @@ -613,15 +615,37 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
> ec->rx_coalesce_usecs =
> bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT) * 8192 / 1000;
>
> + for (i = 0; i < priv->hw_params->rx_queues; i++) {
> + ring = &priv->rx_rings[i];
> + ec->use_adaptive_rx_coalesce |= ring->dim.use_dim;
> + }
> + ring = &priv->rx_rings[DESC_INDEX];
> + ec->use_adaptive_rx_coalesce |= ring->dim.use_dim;
> +
> return 0;
> }
>
> +static void bcmgenet_set_rx_coalesce(struct bcmgenet_rx_ring *ring)
> +{
> + struct bcmgenet_priv *priv = ring->priv;
> + unsigned int i = ring->index;
> + u32 reg;
> +
> + bcmgenet_rdma_ring_writel(priv, i, ring->dim.coal_pkts,
> + DMA_MBUF_DONE_THRESH);
> +
> + reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
> + reg &= ~DMA_TIMEOUT_MASK;
> + reg |= DIV_ROUND_UP(ring->dim.coal_usecs * 1000, 8192);
> + bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
> +}
> +
Similar comments from path 1/2 apply here - wouldn't couple the genric
get_set_coalesce functions with dim.
> static int bcmgenet_set_coalesce(struct net_device *dev,
> struct ethtool_coalesce *ec)
> {
> struct bcmgenet_priv *priv = netdev_priv(dev);
> + struct bcmgenet_rx_ring *ring;
> unsigned int i;
> - u32 reg;
>
> /* Base system clock is 125Mhz, DMA timeout is this reference clock
> * divided by 1024, which yields roughly 8.192us, our maximum value
> @@ -641,7 +665,8 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
> * transmitted, or when the ring is empty.
> */
> if (ec->tx_coalesce_usecs || ec->tx_coalesce_usecs_high ||
> - ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_low)
> + ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_low ||
> + ec->use_adaptive_tx_coalesce)
> return -EOPNOTSUPP;
>
> /* Program all TX queues with the same values, as there is no
> @@ -656,24 +681,26 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
> DMA_MBUF_DONE_THRESH);
>
> for (i = 0; i < priv->hw_params->rx_queues; i++) {
> - bcmgenet_rdma_ring_writel(priv, i,
> - ec->rx_max_coalesced_frames,
> - DMA_MBUF_DONE_THRESH);
> -
> - reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
> - reg &= ~DMA_TIMEOUT_MASK;
> - reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192);
> - bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
> + ring = &priv->rx_rings[i];
> + ring->dim.coal_usecs = ec->rx_coalesce_usecs;
> + ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
> + if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
> + ring->dim.coal_pkts = 1;
> + ring->dim.coal_usecs = 0;
> + }
> + ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
> + bcmgenet_set_rx_coalesce(ring);
> }
>
> - bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
> - ec->rx_max_coalesced_frames,
> - DMA_MBUF_DONE_THRESH);
> -
> - reg = bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT);
> - reg &= ~DMA_TIMEOUT_MASK;
> - reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192);
> - bcmgenet_rdma_writel(priv, reg, DMA_RING16_TIMEOUT);
> + ring = &priv->rx_rings[DESC_INDEX];
> + ring->dim.coal_usecs = ec->rx_coalesce_usecs;
> + ring->dim.coal_pkts = ec->rx_max_coalesced_frames;
> + if (!ec->use_adaptive_rx_coalesce && ring->dim.use_dim) {
> + ring->dim.coal_pkts = 1;
> + ring->dim.coal_usecs = 0;
> + }
> + ring->dim.use_dim = ec->use_adaptive_rx_coalesce;
> + bcmgenet_set_rx_coalesce(ring);
>
> return 0;
> }
> @@ -1713,6 +1740,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
> unsigned long dma_flag;
> int len;
> unsigned int rxpktprocessed = 0, rxpkttoprocess;
> + unsigned int bytes_processed = 0;
> unsigned int p_index, mask;
> unsigned int discards;
> unsigned int chksum_ok = 0;
> @@ -1832,6 +1860,8 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
> len -= ETH_FCS_LEN;
> }
>
> + bytes_processed += len;
> +
> /*Finish setting up the received SKB and send it to the kernel*/
> skb->protocol = eth_type_trans(skb, priv->dev);
> ring->packets++;
> @@ -1854,6 +1884,9 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
> bcmgenet_rdma_ring_writel(priv, ring->index, ring->c_index, RDMA_CONS_INDEX);
> }
>
> + ring->dim.bytes = bytes_processed;
> + ring->dim.packets = rxpktprocessed;
> +
> return rxpktprocessed;
> }
>
> @@ -1862,6 +1895,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
> {
> struct bcmgenet_rx_ring *ring = container_of(napi,
> struct bcmgenet_rx_ring, napi);
> + struct net_dim_sample dim_sample;
> unsigned int work_done;
>
> work_done = bcmgenet_desc_rx(ring, budget);
> @@ -1871,9 +1905,32 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
> ring->int_enable(ring);
> }
>
> + if (ring->dim.use_dim) {
> + net_dim_sample(ring->dim.event_ctr, ring->dim.packets,
> + ring->dim.bytes, &dim_sample);
> + net_dim(&ring->dim.dim, dim_sample);
> + }
> +
> return work_done;
> }
>
> +static void bcmgenet_dim_work(struct work_struct *work)
> +{
> + struct net_dim *dim = container_of(work, struct net_dim, work);
> + struct bcmgenet_net_dim *ndim =
> + container_of(dim, struct bcmgenet_net_dim, dim);
> + struct bcmgenet_rx_ring *ring =
> + container_of(ndim, struct bcmgenet_rx_ring, dim);
> + struct net_dim_cq_moder cur_profile =
> + net_dim_get_profile(dim->mode, dim->profile_ix);
> +
> + ring->dim.coal_usecs = cur_profile.usec;
> + ring->dim.coal_pkts = cur_profile.pkts;
> +
> + bcmgenet_set_rx_coalesce(ring);
> + dim->state = NET_DIM_START_MEASURE;
> +}
> +
> /* Assign skb to RX DMA descriptor. */
> static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv,
> struct bcmgenet_rx_ring *ring)
> @@ -2022,6 +2079,16 @@ static void init_umac(struct bcmgenet_priv *priv)
> dev_dbg(kdev, "done init umac\n");
> }
>
> +static void bcmgenet_init_dim(struct bcmgenet_net_dim *dim,
> + void (*cb)(struct work_struct *work))
> +{
> + INIT_WORK(&dim->dim.work, cb);
> + dim->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
> + dim->event_ctr = 0;
> + dim->packets = 0;
> + dim->bytes = 0;
> +} > +
Similar comment from path 1/2 applies here - default values for
coal_usecs/pkts.
> /* Initialize a Tx ring along with corresponding hardware registers */
> static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
> unsigned int index, unsigned int size,
> @@ -2111,6 +2178,8 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
> if (ret)
> return ret;
>
> + bcmgenet_init_dim(&ring->dim, bcmgenet_dim_work);
> +
> /* Initialize Rx NAPI */
> netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll,
> NAPI_POLL_WEIGHT);
> @@ -2276,10 +2345,12 @@ static void bcmgenet_disable_rx_napi(struct bcmgenet_priv *priv)
> for (i = 0; i < priv->hw_params->rx_queues; ++i) {
> ring = &priv->rx_rings[i];
> napi_disable(&ring->napi);
> + cancel_work_sync(&ring->dim.dim.work);
> }
>
> ring = &priv->rx_rings[DESC_INDEX];
> napi_disable(&ring->napi);
> + cancel_work_sync(&ring->dim.dim.work);
> }
>
> static void bcmgenet_fini_rx_napi(struct bcmgenet_priv *priv)
> @@ -2557,6 +2628,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
> continue;
>
> rx_ring = &priv->rx_rings[index];
> + rx_ring->dim.event_ctr++;
>
> if (likely(napi_schedule_prep(&rx_ring->napi))) {
> rx_ring->int_disable(rx_ring);
> @@ -2601,6 +2673,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
>
> if (status & UMAC_IRQ_RXDMA_DONE) {
> rx_ring = &priv->rx_rings[DESC_INDEX];
> + rx_ring->dim.event_ctr++;
>
> if (likely(napi_schedule_prep(&rx_ring->napi))) {
> rx_ring->int_disable(rx_ring);
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> index 3c50431ccd2a..22c41e0430fb 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
> @@ -16,6 +16,7 @@
> #include <linux/mii.h>
> #include <linux/if_vlan.h>
> #include <linux/phy.h>
> +#include <linux/net_dim.h>
>
> /* total number of Buffer Descriptors, same for Rx/Tx */
> #define TOTAL_DESC 256
> @@ -572,6 +573,16 @@ struct bcmgenet_tx_ring {
> struct bcmgenet_priv *priv;
> };
>
> +struct bcmgenet_net_dim {
> + u16 use_dim;
> + u16 event_ctr;
> + unsigned long packets;
> + unsigned long bytes;
> + u32 coal_usecs;
> + u32 coal_pkts;
> + struct net_dim dim;
> +};
> +
> struct bcmgenet_rx_ring {
> struct napi_struct napi; /* Rx NAPI struct */
> unsigned long bytes;
> @@ -586,6 +597,7 @@ struct bcmgenet_rx_ring {
> unsigned int cb_ptr; /* Rx ring initial CB ptr */
> unsigned int end_ptr; /* Rx ring end CB ptr */
> unsigned int old_discards;
> + struct bcmgenet_net_dim dim;
> void (*int_enable)(struct bcmgenet_rx_ring *);
> void (*int_disable)(struct bcmgenet_rx_ring *);
> struct bcmgenet_priv *priv;
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox