* [RFC v2 0/3] Add VRF support for VXLAN underlay
From: Alexis Bauvin @ 2018-11-19 17:19 UTC (permalink / raw)
To: dsa, roopa; +Cc: netdev, abauvin, akherbouche
v0 -> v1:
- fix typos
v1 -> v2:
- move vxlan_get_l3mdev from vxlan driver to l3mdev driver as
l3mdev_master_upper_ifindex_by_index
- vxlan: rename variables named l3mdev_ifindex to ifindex
We are trying to isolate the VXLAN traffic from different VMs with VRF as shown
in the schemas below:
+-------------------------+ +----------------------------+
| +----------+ | | +------------+ |
| | | | | | | |
| | tap-red | | | | tap-blue | |
| | | | | | | |
| +----+-----+ | | +-----+------+ |
| | | | | |
| | | | | |
| +----+---+ | | +----+----+ |
| | | | | | | |
| | br-red | | | | br-blue | |
| | | | | | | |
| +----+---+ | | +----+----+ |
| | | | | |
| | | | | |
| | | | | |
| +----+--------+ | | +--------------+ |
| | | | | | | |
| | vxlan-red | | | | vxlan-blue | |
| | | | | | | |
| +------+------+ | | +-------+------+ |
| | | | | |
| | VRF | | | VRF |
| | red | | | blue |
+-------------------------+ +----------------------------+
| |
| |
+---------------------------------------------------------+
| | | |
| | | |
| | +--------------+ | |
| | | | | |
| +---------+ eth0.2030 +---------+ |
| | 10.0.0.1/24 | |
| +-----+--------+ VRF |
| | green|
+---------------------------------------------------------+
|
|
+----+---+
| |
| eth0 |
| |
+--------+
iproute2 commands to reproduce the setup:
ip link add green type vrf table 1
ip link set green up
ip link add eth0.2030 link eth0 type vlan id 2030
ip link set eth0.2030 master green
ip addr add 10.0.0.1/24 dev eth0.2030
ip link set eth0.2030 up
ip link add blue type vrf table 2
ip link set blue up
ip link add br-blue type bridge
ip link set br-blue master blue
ip link set br-blue up
ip link add vxlan-blue type vxlan id 2 local 10.0.0.1 dev eth0.2030 \
port 4789
ip link set vxlan-blue master br-blue
ip link set vxlan-blue up
ip link set tap-blue master br-blue
ip link set tap-blue up
ip link add red type vrf table 3
ip link set red up
ip link add br-red type bridge
ip link set br-red master red
ip link set br-red up
ip link add vxlan-red type vxlan id 3 local 10.0.0.1 dev eth0.2030 \
port 4789
ip link set vxlan-red master br-red
ip link set vxlan-red up
ip link set tap-red master br-red
ip link set tap-red up
We faced some issue in the datapath, here are the details:
* Egress traffic:
The vxlan packets are sent directly to the default VRF because it's where the
socket is bound, therefore the traffic has a default route via eth0. the
workarount is to force this traffic to VRF green with ip rules.
* Ingress traffic:
When receiving the traffic on eth0.2030 the vxlan socket is unreachable from
VRF green. The workaround is to enable *udp_l3mdev_accept* sysctl, but
this breaks isolation between overlay and underlay: packets sent from
blue or red by e.g. a guest VM will be accepted by the socket, allowing
injection of VXLAN packets from the overlay.
This patch serie fixes the issues describe above by allowing VXLAN socket to be
bound to a specific VRF device therefore looking up in the correct table.
Alexis Bauvin (3):
udp_tunnel: add config option to bind to a device
vxlan: add support for underlay in non-default VRF
vxlan: handle underlay VRF changes
drivers/net/vxlan.c | 126 +++++++++++++++++++++++++++++++++++---
include/net/l3mdev.h | 21 +++++++
include/net/udp_tunnel.h | 1 +
net/ipv4/udp_tunnel.c | 10 +++
net/ipv6/ip6_udp_tunnel.c | 9 +++
net/l3mdev/l3mdev.c | 18 ++++++
6 files changed, 177 insertions(+), 8 deletions(-)
--
^ permalink raw reply
* [RFC v2 1/3] udp_tunnel: add config option to bind to a device
From: Alexis Bauvin @ 2018-11-19 17:19 UTC (permalink / raw)
To: dsa, roopa; +Cc: netdev, abauvin, akherbouche
In-Reply-To: <20181119171929.69743-1-abauvin@scaleway.com>
UDP tunnel sockets are always opened unbound to a specific device. This
patch allow the socket to be bound on a custom device, which
incidentally makes UDP tunnels VRF-aware if binding to an l3mdev.
Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
---
include/net/udp_tunnel.h | 1 +
net/ipv4/udp_tunnel.c | 10 ++++++++++
net/ipv6/ip6_udp_tunnel.c | 9 +++++++++
3 files changed, 20 insertions(+)
diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index fe680ab6b15a..9f7970d010f9 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -30,6 +30,7 @@ struct udp_port_cfg {
__be16 local_udp_port;
__be16 peer_udp_port;
+ int bind_ifindex;
unsigned int use_udp_checksums:1,
use_udp6_tx_checksums:1,
use_udp6_rx_checksums:1,
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c
index 6539ff15e9a3..dc68e15a4f72 100644
--- a/net/ipv4/udp_tunnel.c
+++ b/net/ipv4/udp_tunnel.c
@@ -20,6 +20,16 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
if (err < 0)
goto error;
+ if (cfg->bind_ifindex) {
+ struct net_device *dev;
+
+ dev = __dev_get_by_index(net, cfg->bind_ifindex);
+ err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+ dev->name, strlen(dev->name) + 1);
+ if (err < 0)
+ goto error;
+ }
+
udp_addr.sin_family = AF_INET;
udp_addr.sin_addr = cfg->local_ip;
udp_addr.sin_port = cfg->local_udp_port;
diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c
index b283f293ee4a..fc3811ef8787 100644
--- a/net/ipv6/ip6_udp_tunnel.c
+++ b/net/ipv6/ip6_udp_tunnel.c
@@ -31,6 +31,15 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
if (err < 0)
goto error;
}
+ if (cfg->bind_ifindex) {
+ struct net_device *dev;
+
+ dev = __dev_get_by_index(net, cfg->bind_ifindex);
+ err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+ dev->name, strlen(dev->name) + 1);
+ if (err < 0)
+ goto error;
+ }
udp6_addr.sin6_family = AF_INET6;
memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,
--
^ permalink raw reply related
* [RFC v2 2/3] vxlan: add support for underlay in non-default VRF
From: Alexis Bauvin @ 2018-11-19 17:19 UTC (permalink / raw)
To: dsa, roopa; +Cc: netdev, abauvin, akherbouche
In-Reply-To: <20181119171929.69743-1-abauvin@scaleway.com>
Creating a VXLAN device with is underlay in the non-default VRF makes
egress route lookup fail or incorrect since it will resolve in the
default VRF, and ingress fail because the socket listens in the default
VRF.
This patch binds the underlying UDP tunnel socket to the l3mdev of the
lower device of the VXLAN device. This will listen in the proper VRF and
output traffic from said l3mdev, matching l3mdev routing rules and
looking up the correct routing table.
When the VXLAN device does not have a lower device, or the lower device
is in the default VRF, the socket will not be bound to any interface,
keeping the previous behaviour.
The underlay l3mdev is deduced from the VXLAN lower device
(IFLA_VXLAN_LINK).
The l3mdev_master_upper_ifindex_by_index function has been added to
l3mdev. Its goal is to fetch the effective l3mdev of an interface which
is not a direct slave of said l3mdev. It handles the following example,
properly resolving the l3mdev of eth0 to vrf-blue:
+----------+ +---------+
| | | |
| vrf-blue | | vrf-red |
| | | |
+----+-----+ +----+----+
| |
| |
+----+-----+ +----+----+
| | | |
| br-blue | | br-red |
| | | |
+----+-----+ +---+-+---+
| | |
| +-----+ +-----+
| | |
+----+-----+ +------+----+ +----+----+
| | lower device | | | |
| eth0 | <- - - - - - - | vxlan-red | | tap-red | (... more taps)
| | | | | |
+----------+ +-----------+ +---------+
Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
---
drivers/net/vxlan.c | 32 ++++++++++++++++++++++++--------
include/net/l3mdev.h | 21 +++++++++++++++++++++
net/l3mdev/l3mdev.c | 18 ++++++++++++++++++
3 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 27bd586b94b0..a3de08122269 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -212,7 +212,7 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
* and enabled unshareable flags.
*/
static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
- __be16 port, u32 flags)
+ __be16 port, u32 flags, int ifindex)
{
struct vxlan_sock *vs;
@@ -221,7 +221,8 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
if (inet_sk(vs->sock->sk)->inet_sport == port &&
vxlan_get_sk_family(vs) == family &&
- vs->flags == flags)
+ vs->flags == flags &&
+ vs->sock->sk->sk_bound_dev_if == ifindex)
return vs;
}
return NULL;
@@ -261,7 +262,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex,
{
struct vxlan_sock *vs;
- vs = vxlan_find_sock(net, family, port, flags);
+ vs = vxlan_find_sock(net, family, port, flags, ifindex);
if (!vs)
return NULL;
@@ -2172,6 +2173,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct rtable *rt;
__be16 df = 0;
+ if (!ifindex)
+ ifindex = sock4->sock->sk->sk_bound_dev_if;
+
rt = vxlan_get_route(vxlan, dev, sock4, skb, ifindex, tos,
dst->sin.sin_addr.s_addr,
&local_ip.sin.sin_addr.s_addr,
@@ -2210,6 +2214,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
} else {
struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
+ if (!ifindex)
+ ifindex = sock6->sock->sk->sk_bound_dev_if;
+
ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ifindex, tos,
label, &dst->sin6.sin6_addr,
&local_ip.sin6.sin6_addr,
@@ -2813,7 +2820,7 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
};
static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
- __be16 port, u32 flags)
+ __be16 port, u32 flags, int ifindex)
{
struct socket *sock;
struct udp_port_cfg udp_conf;
@@ -2831,6 +2838,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
}
udp_conf.local_udp_port = port;
+ udp_conf.bind_ifindex = ifindex;
/* Open UDP socket */
err = udp_sock_create(net, &udp_conf, &sock);
@@ -2842,7 +2850,8 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
/* Create new listen socket if needed */
static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
- __be16 port, u32 flags)
+ __be16 port, u32 flags,
+ int ifindex)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct vxlan_sock *vs;
@@ -2857,7 +2866,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
for (h = 0; h < VNI_HASH_SIZE; ++h)
INIT_HLIST_HEAD(&vs->vni_list[h]);
- sock = vxlan_create_sock(net, ipv6, port, flags);
+ sock = vxlan_create_sock(net, ipv6, port, flags, ifindex);
if (IS_ERR(sock)) {
kfree(vs);
return ERR_CAST(sock);
@@ -2894,11 +2903,17 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
struct vxlan_sock *vs = NULL;
struct vxlan_dev_node *node;
+ int l3mdev_index;
+
+ l3mdev_index =
+ l3mdev_master_upper_ifindex_by_index(vxlan->net,
+ vxlan->cfg.remote_ifindex);
if (!vxlan->cfg.no_share) {
spin_lock(&vn->sock_lock);
vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
- vxlan->cfg.dst_port, vxlan->cfg.flags);
+ vxlan->cfg.dst_port, vxlan->cfg.flags,
+ l3mdev_index);
if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
spin_unlock(&vn->sock_lock);
return -EBUSY;
@@ -2907,7 +2922,8 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
}
if (!vs)
vs = vxlan_socket_create(vxlan->net, ipv6,
- vxlan->cfg.dst_port, vxlan->cfg.flags);
+ vxlan->cfg.dst_port, vxlan->cfg.flags,
+ l3mdev_index);
if (IS_ERR(vs))
return PTR_ERR(vs);
#if IS_ENABLED(CONFIG_IPV6)
diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
index 3832099289c5..2c02bf003b21 100644
--- a/include/net/l3mdev.h
+++ b/include/net/l3mdev.h
@@ -101,6 +101,17 @@ struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
return master;
}
+int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex);
+static inline
+int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
+{
+ rcu_read_lock();
+ ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex);
+ rcu_read_unlock();
+
+ return ifindex;
+}
+
u32 l3mdev_fib_table_rcu(const struct net_device *dev);
u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
static inline u32 l3mdev_fib_table(const struct net_device *dev)
@@ -207,6 +218,16 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
return 0;
}
+static
+int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
+{
+ return 0;
+}
+static int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
+{
+ return 0;
+}
+
static inline
struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
{
diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
index 8da86ceca33d..309dee76724e 100644
--- a/net/l3mdev/l3mdev.c
+++ b/net/l3mdev/l3mdev.c
@@ -46,6 +46,24 @@ int l3mdev_master_ifindex_rcu(const struct net_device *dev)
}
EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu);
+/**
+ * l3mdev_master_upper_ifindex_by_index - get index of upper l3 master
+ * device
+ * @net: network namespace for device index lookup
+ * @ifindex: targeted interface
+ */
+int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
+{
+ struct net_device *dev;
+
+ dev = dev_get_by_index_rcu(net, ifindex);
+ while (dev && !netif_is_l3_master(dev))
+ dev = netdev_master_upper_dev_get(dev);
+
+ return dev ? dev->ifindex : 0;
+}
+EXPORT_SYMBOL_GPL(l3mdev_master_upper_ifindex_by_index_rcu);
+
/**
* l3mdev_fib_table - get FIB table id associated with an L3
* master interface
--
^ permalink raw reply related
* [RFC v2 3/3] vxlan: handle underlay VRF changes
From: Alexis Bauvin @ 2018-11-19 17:19 UTC (permalink / raw)
To: dsa, roopa; +Cc: netdev, abauvin, akherbouche
In-Reply-To: <20181119171929.69743-1-abauvin@scaleway.com>
When underlay VRF changes, either because the lower device itself changed,
or its VRF changed, this patch releases the current socket of the VXLAN
device and recreates another one in the right VRF. This allows for
on-the-fly change of the underlay VRF of a VXLAN device.
Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
---
drivers/net/vxlan.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index a3de08122269..13ed9569ec79 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -208,6 +208,18 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
}
+static int vxlan_is_in_l3mdev_chain(struct net_device *chain,
+ struct net_device *dev)
+{
+ if (!chain)
+ return 0;
+
+ if (chain->ifindex == dev->ifindex)
+ return 1;
+ return vxlan_is_in_l3mdev_chain(netdev_master_upper_dev_get(chain),
+ dev);
+}
+
/* Find VXLAN socket based on network namespace, address family and UDP port
* and enabled unshareable flags.
*/
@@ -3720,6 +3732,33 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name,
}
EXPORT_SYMBOL_GPL(vxlan_dev_create);
+static int vxlan_reopen(struct vxlan_net *vn, struct vxlan_dev *vxlan)
+{
+ int ret = 0;
+
+ if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
+ !vxlan_group_used(vn, vxlan))
+ ret = vxlan_igmp_leave(vxlan);
+ vxlan_sock_release(vxlan);
+
+ if (ret < 0)
+ return ret;
+
+ ret = vxlan_sock_add(vxlan);
+ if (ret < 0)
+ return ret;
+
+ if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
+ ret = vxlan_igmp_join(vxlan);
+ if (ret == -EADDRINUSE)
+ ret = 0;
+ if (ret)
+ vxlan_sock_release(vxlan);
+ }
+
+ return ret;
+}
+
static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
struct net_device *dev)
{
@@ -3742,6 +3781,55 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
unregister_netdevice_many(&list_kill);
}
+static void vxlan_handle_change_upper(struct vxlan_net *vn,
+ struct net_device *dev)
+{
+ struct vxlan_dev *vxlan, *next;
+
+ list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
+ struct net_device *lower;
+ int err;
+
+ lower = __dev_get_by_index(vxlan->net,
+ vxlan->cfg.remote_ifindex);
+ if (!vxlan_is_in_l3mdev_chain(lower, dev))
+ continue;
+
+ err = vxlan_reopen(vn, vxlan);
+ if (err < 0)
+ netdev_err(vxlan->dev, "Failed to reopen socket: %d\n",
+ err);
+ }
+}
+
+static void vxlan_handle_change(struct vxlan_net *vn, struct net_device *dev)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct vxlan_sock *sock;
+ int l3mdev_index;
+
+#if IS_ENABLED(CONFIG_IPV6)
+ bool metadata = vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA;
+ bool ipv6 = vxlan->cfg.flags & VXLAN_F_IPV6 || metadata;
+#else
+ bool ipv6 = false;
+#endif
+
+ l3mdev_index =
+ l3mdev_master_upper_ifindex_by_index(vxlan->net,
+ vxlan->cfg.remote_ifindex);
+
+ sock = ipv6 ? rcu_dereference(vxlan->vn6_sock)
+ : rcu_dereference(vxlan->vn4_sock);
+ if (sock->sock->sk->sk_bound_dev_if != l3mdev_index) {
+ int ret = vxlan_reopen(vn, vxlan);
+
+ if (ret < 0)
+ netdev_err(vxlan->dev, "Failed to reopen socket: %d\n",
+ ret);
+ }
+}
+
static int vxlan_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -3756,6 +3844,12 @@ static int vxlan_netdevice_event(struct notifier_block *unused,
} else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO ||
event == NETDEV_UDP_TUNNEL_DROP_INFO) {
vxlan_offload_rx_ports(dev, event == NETDEV_UDP_TUNNEL_PUSH_INFO);
+ } else if (event == NETDEV_CHANGEUPPER) {
+ vxlan_handle_change_upper(vn, dev);
+ } else if (event == NETDEV_CHANGE) {
+ if (dev->rtnl_link_ops &&
+ !strcmp(dev->rtnl_link_ops->kind, vxlan_link_ops.kind))
+ vxlan_handle_change(vn, dev);
}
return NOTIFY_DONE;
--
^ permalink raw reply related
* Re: [PATCH net] sctp: not allow to set asoc prsctp_enable by sockopt
From: Neil Horman @ 2018-11-19 17:26 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: Xin Long, network dev, linux-sctp, davem
In-Reply-To: <20181119041450.GB3601@localhost.localdomain>
On Mon, Nov 19, 2018 at 02:14:50AM -0200, Marcelo Ricardo Leitner wrote:
> On Sun, Nov 18, 2018 at 04:02:25PM +0900, Xin Long wrote:
> > On Sat, Nov 17, 2018 at 12:12 AM Neil Horman <nhorman@tuxdriver.com> wrote:
> > >
> > > On Thu, Nov 15, 2018 at 09:41:01PM -0200, Marcelo Ricardo Leitner wrote:
> > > > [ re-sending, without html this time ]
> > > >
> > > > On Thu, Nov 15, 2018, 15:26 Neil Horman <nhorman@tuxdriver.com wrote:
> > > >
> > > > > On Thu, Nov 15, 2018 at 08:25:36PM -0200, Marcelo Ricardo Leitner wrote:
> > > > > > On Thu, Nov 15, 2018 at 04:43:10PM -0500, Neil Horman wrote:
> > > > > > > On Thu, Nov 15, 2018 at 03:22:21PM -0200, Marcelo Ricardo Leitner
> > > > > wrote:
> > > > > > > > On Thu, Nov 15, 2018 at 07:14:28PM +0800, Xin Long wrote:
> > > > > > > > > As rfc7496#section4.5 says about SCTP_PR_SUPPORTED:
> > > > > > > > >
> > > > > > > > > This socket option allows the enabling or disabling of the
> > > > > > > > > negotiation of PR-SCTP support for future associations. For
> > > > > existing
> > > > > > > > > associations, it allows one to query whether or not PR-SCTP
> > > > > support
> > > > > > > > > was negotiated on a particular association.
> > > > > > > > >
> > > > > > > > > It means only sctp sock's prsctp_enable can be set.
> > > > > > > > >
> > > > > > > > > Note that for the limitation of SCTP_{CURRENT|ALL}_ASSOC, we will
> > > > > > > > > add it when introducing SCTP_{FUTURE|CURRENT|ALL}_ASSOC for linux
> > > > > > > > > sctp in another patchset.
> > > > > > > > >
> > > > > > > > > Fixes: 28aa4c26fce2 ("sctp: add SCTP_PR_SUPPORTED on sctp sockopt")
> > > > > > > > > Reported-by: Ying Xu <yinxu@redhat.com>
> > > > > > > > > Signed-off-by: Xin Long <lucien.xin@gmail.com>
> > > > > > > > > ---
> > > > > > > > > net/sctp/socket.c | 13 +++----------
> > > > > > > > > 1 file changed, 3 insertions(+), 10 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> > > > > > > > > index 739f3e5..e9b8232 100644
> > > > > > > > > --- a/net/sctp/socket.c
> > > > > > > > > +++ b/net/sctp/socket.c
> > > > > > > > > @@ -3940,7 +3940,6 @@ static int
> > > > > sctp_setsockopt_pr_supported(struct sock *sk,
> > > > > > > > > unsigned int optlen)
> > > > > > > > > {
> > > > > > > > > struct sctp_assoc_value params;
> > > > > > > > > - struct sctp_association *asoc;
> > > > > > > > > int retval = -EINVAL;
> > > > > > > > >
> > > > > > > > > if (optlen != sizeof(params))
> > > > > > > > > @@ -3951,16 +3950,10 @@ static int
> > > > > sctp_setsockopt_pr_supported(struct sock *sk,
> > > > > > > > > goto out;
> > > > > > > > > }
> > > > > > > > >
> > > > > > > > > - asoc = sctp_id2assoc(sk, params.assoc_id);
> > > > > > > > > - if (asoc) {
> > > > > > > > > - asoc->prsctp_enable = !!params.assoc_value;
> > > > > > > > > - } else if (!params.assoc_id) {
> > > > > > > > > - struct sctp_sock *sp = sctp_sk(sk);
> > > > > > > > > -
> > > > > > > > > - sp->ep->prsctp_enable = !!params.assoc_value;
> > > > > > > > > - } else {
> > > > > > > > > + if (sctp_style(sk, UDP) && sctp_id2assoc(sk,
> > > > > params.assoc_id))
> > > > > > > >
> > > > > > > > This would allow using a non-existent assoc id on UDP-style sockets
> > > > > to
> > > > > > > > set it at the socket, which is not expected. It should be more like:
> > > > > > > >
> > > > > > > > + if (sctp_style(sk, UDP) && params.assoc_id)
> > > > > > > How do you see that to be the case? sctp_id2assoc will return NULL if
> > > > > an
> > > > > > > association isn't found, so the use of sctp_id2assoc should work just
> > > > > fine.
> > > > > >
> > > > > > Right, it will return NULL, and because of that it won't bail out as
> > > > > > it should and will adjust the socket config instead.
> > > > > >
> > > > >
> > > > > Oh, duh, you're absolutely right, NULL will evalutate to false there, and
> > > > > skip
> > > > > the conditional goto out;
> > > > >
> > > > > that said, It would make more sense to me to just change the sense of the
> > > > > second
> > > > > condition to !sctp_id2assoc(sk, params.assoc_id), so that we goto out if no
> > > > > association is found. it still seems a
> > > >
> > > >
> > > > That would break setting it on the socket without an assoc so far.
> > > >
> > > ok, yes, I see what xin is getting at now. The RFC indicates that the
> > > setsockopt method for this socket option is meant to set the prsctp enabled
> > > value on _future_ associations, implying that we should not operate at all on
> > > already existing associations (i.e. we should ignore the assoc_id in the passed
> > > in structure and only operate on the socket). That said, heres the entire text
> > > of the RFC section:
> > >
> > > 4.5. Socket Option for Getting and Setting the PR-SCTP Support
> > > (SCTP_PR_SUPPORTED)
> > >
> > > This socket option allows the enabling or disabling of the
> > > negotiation of PR-SCTP support for future associations. For existing
> > > associations, it allows one to query whether or not PR-SCTP support
> > > was negotiated on a particular association.
> > >
> > > Whether or not PR-SCTP is enabled by default is implementation
> > > specific.
> > >
> > > This socket option uses IPPROTO_SCTP as its level and
> > > SCTP_PR_SUPPORTED as its name. It can be used with getsockopt() and
> > > setsockopt(). The socket option value uses the following structure
> > > defined in [RFC6458]:
> > >
> > > struct sctp_assoc_value {
> > > sctp_assoc_t assoc_id;
> > > uint32_t assoc_value;
> > > };
> > >
> > > assoc_id: This parameter is ignored for one-to-one style sockets.
> > > For one-to-many style sockets, this parameter indicates upon which
> > > association the user is performing an action. The special
> > > sctp_assoc_t SCTP_FUTURE_ASSOC can also be used; it is an error to
> > > use SCTP_{CURRENT|ALL}_ASSOC in assoc_id.
> > >
> > > assoc_value: A non-zero value encodes the enabling of PR-SCTP,
> > > whereas a value of 0 encodes the disabling of PR-SCTP.
> > >
> > > sctp_opt_info() needs to be extended to support SCTP_PR_SUPPORTED
> > >
> > > My read of this suggests that for setting the prsctp_enabled flag, we only need
> > > a valid socket (the presence or lack of associations is irrelevant), its only
> > > for the getsockopt method that we need to specify an assoc_id, as the getsockopt
> > > method operates on associations, while the setsockopt method operates at the
> > > socket level (to be inherited as association init).
> > >
> > > Given that, I'd argue that we can skip the check entirely, and just assign
> > > sctp_sock(sk)->prsctp_enabled = !!param.assoc_value
> > >
> > > directly.
> > RFC seems to have no clear demands for this, I will just drop the check
> > in this patch, thanks.
>
> RFC may not have clear demands, but I still don't see a reason for not
> rejecting bogus arguments that can potentially lead to confusion.
> We usually do argument parsing in the other way around: restrict as
> much as possible, and relax when needed. That avoids applications to
> build bad behaviors that we would end up having to cope with it.
> Anyhow, I won't oppose to this any further.
>
I think we could make the same argument about the assoc_value field on the
getsockopt method. Its an output in that path, but we make no checks regarding
its input value.
It seems the long and short of it here is that this interface is overloaded for
multiple functions and some values are simply don't care states in certain
paths. What we should do is document it as such in a subsequent version of the
RFC and any related man pages. What we shouldn't do is impose artificial
constraints on those don't care values where none need to exist.
Neil
> @Dave: please give me till Tue to review the other patches. I'm
> traveling and will be offline till Mon night. Thanks.
>
> Marcelo
>
^ permalink raw reply
* Re: [PATCHv3 net-next 0/4] sctp: add subscribe per asoc and sockopt SCTP_EVENT
From: Neil Horman @ 2018-11-19 17:33 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem
In-Reply-To: <cover.1542528309.git.lucien.xin@gmail.com>
On Sun, Nov 18, 2018 at 04:08:50PM +0800, Xin Long wrote:
> This patchset mainly adds the Event Subscription sockopt described in
> rfc6525#section-6.2:
>
> "Subscribing to events as described in [RFC6458] uses a setsockopt()
> call with the SCTP_EVENT socket option. This option takes the
> following structure, which specifies the association, the event type
> (using the same value found in the event type field), and an on/off
> boolean.
>
> struct sctp_event {
> sctp_assoc_t se_assoc_id;
> uint16_t se_type;
> uint8_t se_on;
> };
>
> The user fills in the se_type field with the same value found in the
> strreset_type field, i.e., SCTP_STREAM_RESET_EVENT. The user will
> also fill in the se_assoc_id field with either the association to set
> this event on (this field is ignored for one-to-one style sockets) or
> one of the reserved constant values defined in [RFC6458]. Finally,
> the se_on field is set with a 1 to enable the event or a 0 to disable
> the event."
>
> As for the old SCTP_EVENTS Option with struct sctp_event_subscribe,
> it's being DEPRECATED.
>
> v1->v2:
> - fix some key word in changelog that triggerred the filters at
> vger.kernel.org.
> v2->v3:
> - fix an array out of bounds noticed by Neil in patch 1/4.
>
> Xin Long (4):
> sctp: define subscribe in sctp_sock as __u16
> sctp: add subscribe per asoc
> sctp: rename enum sctp_event to sctp_event_type
> sctp: add sockopt SCTP_EVENT
>
> include/net/sctp/constants.h | 2 +-
> include/net/sctp/sm.h | 4 +-
> include/net/sctp/structs.h | 4 +-
> include/net/sctp/ulpevent.h | 39 ++++++++------
> include/uapi/linux/sctp.h | 13 ++++-
> net/sctp/associola.c | 2 +
> net/sctp/chunk.c | 8 ++-
> net/sctp/primitive.c | 2 +-
> net/sctp/sm_sideeffect.c | 12 ++---
> net/sctp/sm_statetable.c | 2 +-
> net/sctp/socket.c | 125 ++++++++++++++++++++++++++++++++++++++++---
> net/sctp/stream_interleave.c | 12 +++--
> net/sctp/ulpqueue.c | 8 +--
> 13 files changed, 183 insertions(+), 50 deletions(-)
>
> --
> 2.1.0
>
>
Series
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: [PATCH v3] net: Add trace events for all receive exit points
From: Geneviève Bastien @ 2018-11-19 17:47 UTC (permalink / raw)
To: David Miller, mathieu.desnoyers; +Cc: netdev, rostedt, mingo
In-Reply-To: <61fe529f-6f06-65fc-bc1c-043180e86cf9@versatic.net>
On 2018-11-19 10:27 a.m., Geneviève Bastien wrote:
> On 2018-11-18 1:19 a.m., David Miller wrote:
>> From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
>> Date: Sat, 17 Nov 2018 13:27:29 -0500 (EST)
>>
>>> I see two possible solutions:
>>>
>>> 1) Remove the "skb" argument from the sbk_exit tracepoints completely.
>>> Anyway, I think it's not really needed for analysis purposes because
>>> we can link the "entry" with the associated "exit" using the thread ID
>>> executing those tracepoints. (Genevi�ve, would that work for your
>>> analyses ?)
>>>
>>> 2) Move the skb_exit tracepoints before freeing the skb pointer. My
>>> concern here is that the instrumentation may become much uglier than
>>> the currently proposed patch. (I have not looked at the specifics
>>> though, so I may be wrong.)
>>>
>>> Do you have a preference between those two approaches, or perhaps you
>>> have an alternative solution in mind ?
>> I wonder how other situations handle this.
>>
>> About #2, if you put the tracepoint beforehand you can't log the
>> 'ret' value. So at least in that regard I prefer #1.
>>
>> If tracepoints generally handle this by matching up the thread
>> ID, then definitely that's how we should do it here too instead
>> of trying to use the SKB pointer for this purpose.
> I would go for #1 too, the "skb" is not used to match entry/exit, it is more the context in which they appear (thread, softirq, etc). And I did indeed get seg faults on my first attempt when I tried to use the existing templates.
>
> There's just the list tracepoint that would now log nothing, so there's no point looping through the list.
>
After further investigation, the 'netif_receive_skb_list_exit' tracepoint poses a problem: There is no return value in that function and the TRACE_EVENT infrastructure does not support tracepoints without payload, afaik.
Here's a few possible solutions:
1) Add a unique trace_netif_receive_skb_list_exit tracepoint with a 'fake' return value of 0, so it can use the same template as the others. Easiest, but looks hackish.
2) Add tracepoints in the callees in the various locations where individual skbs get removed from the list. But that's quite a few code paths to cover, and we may miss a few.
3) Simply ignore the exit of the list code path. Dependency analyses will miss this case though.
4) Replace the proposed exit tracepoints by others after the delivery of packets, ie in the 'netif_receive_skb_internal' and 'netif_receive_skb_list_internal' functions, again at the risk of missing code paths.
5) None of the above (and fallback to using kretprobes with the tracers)
Any one of these approaches sound more appealing?
Thanks,
Geneviève
^ permalink raw reply
* Re: [PATCH net] Revert "sctp: remove sctp_transport_pmtu_check"
From: Neil Horman @ 2018-11-19 17:50 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, davem, Marcelo Ricardo Leitner
In-Reply-To: <722a49900dadb13e3a97a63d54561418db28e1cc.1542528887.git.lucien.xin@gmail.com>
On Sun, Nov 18, 2018 at 04:14:47PM +0800, Xin Long wrote:
> This reverts commit 22d7be267eaa8114dcc28d66c1c347f667d7878a.
>
> The dst's mtu in transport can be updated by a non sctp place like
> in xfrm where the MTU information didn't get synced between asoc,
> transport and dst, so it is still needed to do the pmtu check
> in sctp_packet_config.
> ---
> include/net/sctp/sctp.h | 12 ++++++++++++
> net/sctp/output.c | 3 +++
> 2 files changed, 15 insertions(+)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 8c2caa3..ab9242e 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -608,4 +608,16 @@ static inline __u32 sctp_dst_mtu(const struct dst_entry *dst)
> SCTP_DEFAULT_MINSEGMENT));
> }
>
> +static inline bool sctp_transport_pmtu_check(struct sctp_transport *t)
> +{
> + __u32 pmtu = sctp_dst_mtu(t->dst);
> +
> + if (t->pathmtu == pmtu)
> + return true;
> +
> + t->pathmtu = pmtu;
> +
> + return false;
> +}
> +
> #endif /* __net_sctp_h__ */
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 67939ad..0860122 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -118,6 +118,9 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
> sctp_transport_route(tp, NULL, sp);
> if (asoc->param_flags & SPP_PMTUD_ENABLE)
> sctp_assoc_sync_pmtu(asoc);
> + } else if (!sctp_transport_pmtu_check(tp)) {
> + if (asoc->param_flags & SPP_PMTUD_ENABLE)
> + sctp_assoc_sync_pmtu(asoc);
> }
>
> if (asoc->pmtu_pending) {
> --
> 2.1.0
>
>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: VETH & AF_PACKET problem
From: Willem de Bruijn @ 2018-11-19 17:54 UTC (permalink / raw)
To: Anand H. Krishnan; +Cc: Network Development
In-Reply-To: <CACeb84sLAPh7oEs2Y+VGFwbuaRkOnw0CvtM0H+Ps-iO597+5Jw@mail.gmail.com>
On Mon, Nov 19, 2018 at 6:00 AM Anand H. Krishnan
<anandhkrishnan@gmail.com> wrote:
>
> Hello,
>
> I tried the 4.19.2 kernel without success. You were probably right
> that skb_orphan
> is indeed called from somewhere in the receive path. I had an
> instrumented kernel
> and the following is what I see:
Thanks for verifying.
I was also able to reproduce it without veth by looping a packet
to another packet socket that delays reading from the socket.
A very preliminary patch is to mark the socket as zerocopy in
tpacket_fill_skb to trigger skb_copy_ubufs whenever the
packet gets cloned or enters the receive path:
@@ -2462,6 +2462,9 @@ static int tpacket_fill_skb(struct packet_sock
*po, struct sk_buff *skb,
skb->tstamp = sockc->transmit_time;
sock_tx_timestamp(&po->sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags);
skb_shinfo(skb)->destructor_arg = ph.raw;
+ skb_shinfo(skb)->tx_flags |= SKBTX_ZEROCOPY_FRAG;
This requires at the least a fixup in skb_zcopy_clear to handle this
special case and not call uarg->callback (because
skb_shinfo(skb)->destructor_arg is of a different type for
tpacket_snd). I'll share a patch to test when I have something
more concrete.
^ permalink raw reply
* Re: KASAN: use-after-free Read in tick_sched_handle (3)
From: Dmitry Vyukov @ 2018-11-20 4:42 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: syzbot, Frédéric Weisbecker, LKML, Ingo Molnar,
syzkaller-bugs, Thomas Gleixner, netdev
In-Reply-To: <20181120041041.GA3398@lerouge>
On Mon, Nov 19, 2018 at 8:10 PM, Frederic Weisbecker
<frederic@kernel.org> wrote:
> On Mon, Nov 19, 2018 at 01:39:02PM -0800, syzbot wrote:
>> Hello,
>>
>> syzbot found the following crash on:
>>
>> HEAD commit: bae4e109837b mlxsw: spectrum: Expose discard counters via ..
>> git tree: net-next
>> console output: https://syzkaller.appspot.com/x/log.txt?x=11b5e77b400000
>> kernel config: https://syzkaller.appspot.com/x/.config?x=d86f24333880b605
>> dashboard link: https://syzkaller.appspot.com/bug?extid=999bca54de2ee169c021
>> compiler: gcc (GCC) 8.0.1 20180413 (experimental)
>> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=14b7d093400000
>> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1487a225400000
>>
>> IMPORTANT: if you fix the bug, please add the following tag to the commit:
>> Reported-by: syzbot+999bca54de2ee169c021@syzkaller.appspotmail.com
>>
>> IPv6: ADDRCONF(NETDEV_CHANGE): veth1: link becomes ready
>> IPv6: ADDRCONF(NETDEV_CHANGE): veth0: link becomes ready
>> 8021q: adding VLAN 0 to HW filter on device team0
>> ==================================================================
>> kasan: CONFIG_KASAN_INLINE enabled
>> BUG: KASAN: use-after-free in tick_sched_handle+0x16c/0x180
>> kernel/time/tick-sched.c:164
>
> So tick_sched_timer() -> tick_sched_handle() is passed regs returned by
> get_irq_regs() that seem to be junk.
>
> Those regs should come from smp_apic_timer_interrupt().
>
> Thoughts?
Looking at the reproducer it looks like some memory corruption in
networking stack. +netdev
^ permalink raw reply
* Re: netns_id in bpf_sk_lookup_{tcp,udp}
From: Joe Stringer @ 2018-11-19 18:36 UTC (permalink / raw)
To: David Ahern; +Cc: Joe Stringer, netdev, daniel
In-Reply-To: <15bf5496-523f-564f-443e-f3262bb9e668@gmail.com>
Hi David, thanks for pointing this out.
This is more of an oversight through iterations, the runtime lookup
will fail to find a socket if the netns value is greater than the
range of a uint32 so I think it would actually make more sense to drop
the parameter size to u32 rather than u64 so that this would be
validated at load time rather than silently returning NULL because of
a bad parameter.
I'll send a patch to bpf tree.
Cheers,
Joe
On Sun, 18 Nov 2018 at 19:27, David Ahern <dsahern@gmail.com> wrote:
>
> Hi Joe:
>
> The netns_id to the bpf_sk_lookup_{tcp,udp} functions in
> net/core/filter.c is a u64, yet the APIs in include/uapi/linux/bpf.h
> shows a u32. Is that intentional or an oversight through the iterations?
>
> David
^ permalink raw reply
* Re: netns_id in bpf_sk_lookup_{tcp,udp}
From: David Ahern @ 2018-11-19 18:39 UTC (permalink / raw)
To: Joe Stringer; +Cc: netdev, daniel
In-Reply-To: <CAOftzPjoAadwrYzhMY_P36D+ZpKAzYBAFth=S3LyGrqKGy9e2g@mail.gmail.com>
On 11/19/18 11:36 AM, Joe Stringer wrote:
> Hi David, thanks for pointing this out.
>
> This is more of an oversight through iterations, the runtime lookup
> will fail to find a socket if the netns value is greater than the
> range of a uint32 so I think it would actually make more sense to drop
> the parameter size to u32 rather than u64 so that this would be
> validated at load time rather than silently returning NULL because of
> a bad parameter.
ok. I was wondering if it was a u64 to handle nsid of 0 which as I
understand it is a legal nsid. If you drop to u32, how do you know when
nsid has been set?
>
> I'll send a patch to bpf tree.
>
ok.
^ permalink raw reply
* Re: [RFCv3 PATCH 1/6] uacce: Add documents for WarpDrive/uacce
From: Jerome Glisse @ 2018-11-19 18:42 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Leon Romanovsky, Kenneth Lee, Tim Sell, linux-doc,
Alexander Shishkin, Zaibo Xu, zhangfei.gao, linuxarm,
haojian.zhuang, Christoph Lameter, Hao Fang, Gavin Schenk,
RDMA mailing list, Zhou Wang, Doug Ledford, Uwe Kleine-König,
David Kershner, Kenneth Lee, Johan Hovold, Cyrille Pitchen
In-Reply-To: <20181119182752.GA4890@ziepe.ca>
On Mon, Nov 19, 2018 at 11:27:52AM -0700, Jason Gunthorpe wrote:
> On Mon, Nov 19, 2018 at 11:48:54AM -0500, Jerome Glisse wrote:
>
> > Just to comment on this, any infiniband driver which use umem and do
> > not have ODP (here ODP for me means listening to mmu notifier so all
> > infiniband driver except mlx5) will be affected by same issue AFAICT.
> >
> > AFAICT there is no special thing happening after fork() inside any of
> > those driver. So if parent create a umem mr before fork() and program
> > hardware with it then after fork() the parent might start using new
> > page for the umem range while the old memory is use by the child. The
> > reverse is also true (parent using old memory and child new memory)
> > bottom line you can not predict which memory the child or the parent
> > will use for the range after fork().
> >
> > So no matter what you consider the child or the parent, what the hw
> > will use for the mr is unlikely to match what the CPU use for the
> > same virtual address. In other word:
> >
> > Before fork:
> > CPU parent: virtual addr ptr1 -> physical address = 0xCAFE
> > HARDWARE: virtual addr ptr1 -> physical address = 0xCAFE
> >
> > Case 1:
> > CPU parent: virtual addr ptr1 -> physical address = 0xCAFE
> > CPU child: virtual addr ptr1 -> physical address = 0xDEAD
> > HARDWARE: virtual addr ptr1 -> physical address = 0xCAFE
> >
> > Case 2:
> > CPU parent: virtual addr ptr1 -> physical address = 0xBEEF
> > CPU child: virtual addr ptr1 -> physical address = 0xCAFE
> > HARDWARE: virtual addr ptr1 -> physical address = 0xCAFE
>
> IIRC this is solved in IB by automatically calling
> madvise(MADV_DONTFORK) before creating the MR.
>
> MADV_DONTFORK
> .. This is useful to prevent copy-on-write semantics from changing the
> physical location of a page if the parent writes to it after a
> fork(2) ..
This would work around the issue but this is not transparent ie
range marked with DONTFORK no longer behave as expected from the
application point of view.
Also it relies on userspace doing the right thing (which is not
something i usualy trust :)).
Cheers,
Jérôme
^ permalink raw reply
* Re: [PATCH mlx5-next 11/12] {net,IB}/mlx5: Move Page fault EQ and ODP logic to RDMA
From: Saeed Mahameed @ 2018-11-19 18:43 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: netdev@vger.kernel.org, Leon Romanovsky,
linux-rdma@vger.kernel.org
In-Reply-To: <20181117201347.GA14593@mellanox.com>
On Sat, 2018-11-17 at 20:13 +0000, Jason Gunthorpe wrote:
> On Fri, Nov 16, 2018 at 01:59:00PM -0800, Saeed Mahameed wrote:
> > Use the new generic EQ API to move all ODP RDMA data structures and
> > logic
> > form mlx5 core driver into mlx5_ib driver.
> >
> > Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> > Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
> > Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
[...]
> >
> > +struct mlx5_ib_pf_eq {
> > + struct mlx5_ib_dev *dev;
> > + struct mlx5_eq *core;
> > + struct work_struct work;
> > + spinlock_t lock; /* Pagefaults spinlock */
> > + struct workqueue_struct *wq;
> > + mempool_t *pool;
> > +};
>
> I know this is being copied, but can we please not do this vertical
> alignment madness in RDMA? It is such a nightmare to maintain this..
>
Ack will fix and submit v2.
> > +/* mempool_refill() was proposed but unfortunately wasn't accepted
> > + * http://lkml.iu.edu/hypermail/linux/kernel/1512.1/05073.html
> > + * Chip workaround.
>
> 'cheap workaround'
>
Will fix
> Jason
^ permalink raw reply
* linux-next: Signed-off-by missing for commit in the net tree
From: Stephen Rothwell @ 2018-11-20 5:15 UTC (permalink / raw)
To: David Miller, Networking
Cc: Linux Next Mailing List, Linux Kernel Mailing List, Xin Long
[-- Attachment #1: Type: text/plain, Size: 170 bytes --]
Hi all,
Commit
69fec325a643 ("Revert "sctp: remove sctp_transport_pmtu_check"")
is missing a Signed-off-by from its author.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH net-next] add part of TCP counts explanations in snmp_counters.rst
From: Stephen Hemminger @ 2018-11-19 18:51 UTC (permalink / raw)
To: yupeng; +Cc: netdev, xiyou.wangcong, rdunlap
In-Reply-To: <20181116191740.12632-1-yupeng0921@gmail.com>
On Fri, 16 Nov 2018 11:17:40 -0800
yupeng <yupeng0921@gmail.com> wrote:
> +* TcpInSegs
> +Defined in `RFC1213 tcpInSegs`_
> +
> +.. _RFC1213 tcpInSegs: https://tools.ietf.org/html/rfc1213#page-48
> +
> +The number of packets received by the TCP layer. As mentioned in
> +RFC1213, it includes the packets received in error, such as checksum
> +error, invalid TCP header and so on. Only one error won't be included:
> +if the layer 2 destination address is not the NIC's layer 2
> +address. It might happen if the packet is a multicast or broadcast
> +packet, or the NIC is in promiscuous mode. In these situations, the
> +packets would be delivered to the TCP layer, but the TCP layer will discard
> +these packets before increasing TcpInSegs. The TcpInSegs counter
> +isn't aware of GRO. So if two packets are merged by GRO, the TcpInSegs
> +counter would only increase 1.
Is it it obvious that TCP which is L4 masks off all the other things
that could happen at L3 and L2. SO this text is correct but redundant.
^ permalink raw reply
* Re: [RFCv3 PATCH 1/6] uacce: Add documents for WarpDrive/uacce
From: Leon Romanovsky @ 2018-11-20 5:17 UTC (permalink / raw)
To: Kenneth Lee
Cc: Jason Gunthorpe, Kenneth Lee, Tim Sell, linux-doc,
Alexander Shishkin, Zaibo Xu, zhangfei.gao, linuxarm,
haojian.zhuang, Christoph Lameter, Hao Fang, Gavin Schenk,
RDMA mailing list, Zhou Wang, Doug Ledford, Uwe Kleine-König,
David Kershner, Johan Hovold, Cyrille Pitchen, Sagar Dharia
In-Reply-To: <20181120030702.GH157308@Turing-Arch-b>
[-- Attachment #1: Type: text/plain, Size: 6286 bytes --]
On Tue, Nov 20, 2018 at 11:07:02AM +0800, Kenneth Lee wrote:
> On Mon, Nov 19, 2018 at 11:49:54AM -0700, Jason Gunthorpe wrote:
> > Date: Mon, 19 Nov 2018 11:49:54 -0700
> > From: Jason Gunthorpe <jgg@ziepe.ca>
> > To: Kenneth Lee <liguozhu@hisilicon.com>
> > CC: Leon Romanovsky <leon@kernel.org>, Kenneth Lee <nek.in.cn@gmail.com>,
> > Tim Sell <timothy.sell@unisys.com>, linux-doc@vger.kernel.org, Alexander
> > Shishkin <alexander.shishkin@linux.intel.com>, Zaibo Xu
> > <xuzaibo@huawei.com>, zhangfei.gao@foxmail.com, linuxarm@huawei.com,
> > haojian.zhuang@linaro.org, Christoph Lameter <cl@linux.com>, Hao Fang
> > <fanghao11@huawei.com>, Gavin Schenk <g.schenk@eckelmann.de>, RDMA mailing
> > list <linux-rdma@vger.kernel.org>, Zhou Wang <wangzhou1@hisilicon.com>,
> > Doug Ledford <dledford@redhat.com>, Uwe Kleine-König
> > <u.kleine-koenig@pengutronix.de>, David Kershner
> > <david.kershner@unisys.com>, Johan Hovold <johan@kernel.org>, Cyrille
> > Pitchen <cyrille.pitchen@free-electrons.com>, Sagar Dharia
> > <sdharia@codeaurora.org>, Jens Axboe <axboe@kernel.dk>,
> > guodong.xu@linaro.org, linux-netdev <netdev@vger.kernel.org>, Randy Dunlap
> > <rdunlap@infradead.org>, linux-kernel@vger.kernel.org, Vinod Koul
> > <vkoul@kernel.org>, linux-crypto@vger.kernel.org, Philippe Ombredanne
> > <pombredanne@nexb.com>, Sanyog Kale <sanyog.r.kale@intel.com>, "David S.
> > Miller" <davem@davemloft.net>, linux-accelerators@lists.ozlabs.org
> > Subject: Re: [RFCv3 PATCH 1/6] uacce: Add documents for WarpDrive/uacce
> > User-Agent: Mutt/1.9.4 (2018-02-28)
> > Message-ID: <20181119184954.GB4890@ziepe.ca>
> >
> > On Mon, Nov 19, 2018 at 05:14:05PM +0800, Kenneth Lee wrote:
> >
> > > If the hardware cannot share page table with the CPU, we then need to have
> > > some way to change the device page table. This is what happen in ODP. It
> > > invalidates the page table in device upon mmu_notifier call back. But this cannot
> > > solve the COW problem: if the user process A share a page P with device, and A
> > > forks a new process B, and it continue to write to the page. By COW, the
> > > process B will keep the page P, while A will get a new page P'. But you have
> > > no way to let the device know it should use P' rather than P.
> >
> > Is this true? I thought mmu_notifiers covered all these cases.
> >
> > The mm_notifier for A should fire if B causes the physical address of
> > A's pages to change via COW.
> >
> > And this causes the device page tables to re-synchronize.
>
> I don't see such code. The current do_cow_fault() implemenation has nothing to
> do with mm_notifer.
>
> >
> > > In WarpDrive/uacce, we make this simple. If you support IOMMU and it support
> > > SVM/SVA. Everything will be fine just like ODP implicit mode. And you don't need
> > > to write any code for that. Because it has been done by IOMMU framework. If it
> >
> > Looks like the IOMMU code uses mmu_notifier, so it is identical to
> > IB's ODP. The only difference is that IB tends to have the IOMMU page
> > table in the device, not in the CPU.
> >
> > The only case I know if that is different is the new-fangled CAPI
> > stuff where the IOMMU can directly use the CPU's page table and the
> > IOMMU page table (in device or CPU) is eliminated.
> >
>
> Yes. We are not focusing on the current implementation. As mentioned in the
> cover letter. We are expecting Jean Philips' SVA patch:
> git://linux-arm.org/linux-jpb.
>
> > Anyhow, I don't think a single instance of hardware should justify an
> > entire new subsystem. Subsystems are hard to make and without multiple
> > hardware examples there is no way to expect that it would cover any
> > future use cases.
>
> Yes. That's our first expectation. We can keep it with our driver. But because
> there is no user driver support for any accelerator in mainline kernel. Even the
> well known QuickAssit has to be maintained out of tree. So we try to see if
> people is interested in working together to solve the problem.
>
> >
> > If all your driver needs is to mmap some PCI bar space, route
> > interrupts and do DMA mapping then mediated VFIO is probably a good
> > choice.
>
> Yes. That is what is done in our RFCv1/v2. But we accepted Jerome's opinion and
> try not to add complexity to the mm subsystem.
>
> >
> > If it needs to do a bunch of other stuff, not related to PCI bar
> > space, interrupts and DMA mapping (ie special code for compression,
> > crypto, AI, whatever) then you should probably do what Jerome said and
> > make a drivers/char/hisillicon_foo_bar.c that exposes just what your
> > hardware does.
>
> Yes. If no other accelerator driver writer is interested. That is the
> expectation:)
>
> But we really like to have a public solution here. Consider this scenario:
>
> You create some connections (queues) to NIC, RSA, and AI engine. Then you got
> data direct from the NIC and pass the pointer to RSA engine for decryption. The
> CPU then finish some data taking or operation and then pass through to the AI
> engine for CNN calculation....This will need a place to maintain the same
> address space by some means.
You are using NIC terminology, in the documentation, you wrote that it is needed
for DPDK use and I don't really understand, why do we need another shiny new
interface for DPDK.
>
> It is not complex, but it is helpful.
>
> >
> > If you have networking involved in here then consider RDMA,
> > particularly if this functionality is already part of the same
> > hardware that the hns infiniband driver is servicing.
> >
> > 'computational MRs' are a reasonable approach to a side-car offload of
> > already existing RDMA support.
>
> OK. Thanks. I will spend some time on it. But personally, I really don't like
> RDMA's complexity. I cannot even try one single function without a...some
> expensive hardwares and complexity connection in the lab. This is not like a
> open source way.
It is not very accurate. We have RXE driver which is virtual RDMA device
which is implemented purely in SW. It struggles from bad performance and
sporadic failures, but it is enough to try RDMA on your laptop in VM.
Thanks
>
> >
> > Jason
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH V2 mlx5-next 00/12] mlx5 core generic EQ API for RDMA ODP
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
Hi,
This patchset is for mlx5-next shared branch, and will be applied there
once the review is done.
This patchset introduces mostly refactoring work and EQ related code updates to
allow moving the ODP rdma only logic from mlx5_core into mlx5 ib where it
belongs, and will allow future updates and optimizations for the rdma ODP
(On Demand Paging) feature to go only to rdma tree.
Patch #1: Fixes the offsets of stored irq affinity hints inside mlx5
irq info array.
Patch #2,3,4: Remove unused fields, code and logic
Patch #5: Move all EQ related logic from main.c to eq.c to allow clear
and seamless refactoring for creating generic EQ management API.
Patch #6: Create mlx5 core EQs in one place, in order to have one entry
point to call from main file.
Patch #7,8: Move EQ related structures into eq_table mlx5 structure and
make eq_table fields and logic private to eq.c file.
Patch #9,10: Create one generic EQ struct and use it in different
EQ types (usages) e.g. (Async, Command, FW pages, completion and ODP)
Introduce generic EQ API to allow creating Generic EQs regardless of
their types, will be uesd to create all mlx5 core EQs in mlx5_core and
ODP EQ in mlx5_ib.
Patch #11: Move ODP logic out from mlx5_core eq.c into mlx5 rdma driver.
odp.c file.
Patch #12: Make the trivial EQE access methods inline.
v1->v2:
- Remove vertical alignment
- Fix spilling "Chip" -> "Cheap"
Thanks,
Saeed.
---
Saeed Mahameed (12):
net/mlx5: EQ, Use the right place to store/read IRQ affinity hint
net/mlx5: EQ, Remove unused fields and structures
net/mlx5: EQ, No need to store eq index as a field
net/mlx5: EQ, Remove redundant completion EQ list lock
net/mlx5: EQ, Move all EQ logic to eq.c
net/mlx5: EQ, Create all EQs in one place
net/mlx5: EQ, irq_info and rmap belong to eq_table
net/mlx5: EQ, Privatize eq_table and friends
net/mlx5: EQ, Different EQ types
net/mlx5: EQ, Generic EQ
{net,IB}/mlx5: Move Page fault EQ and ODP logic to RDMA
net/mlx5: EQ, Make EQE access methods inline
drivers/infiniband/hw/mlx5/main.c | 15 +-
drivers/infiniband/hw/mlx5/mlx5_ib.h | 15 +-
drivers/infiniband/hw/mlx5/odp.c | 281 ++++-
drivers/net/ethernet/mellanox/mlx5/core/cq.c | 15 +-
.../net/ethernet/mellanox/mlx5/core/debugfs.c | 11 +
drivers/net/ethernet/mellanox/mlx5/core/dev.c | 34 -
drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 +-
.../net/ethernet/mellanox/mlx5/core/en_main.c | 18 +-
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 968 +++++++++++-------
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 3 +-
.../net/ethernet/mellanox/mlx5/core/health.c | 3 +-
.../net/ethernet/mellanox/mlx5/core/lib/eq.h | 93 ++
.../net/ethernet/mellanox/mlx5/core/main.c | 287 +-----
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 23 -
include/linux/mlx5/cq.h | 2 +-
include/linux/mlx5/driver.h | 151 +--
include/linux/mlx5/eq.h | 60 ++
17 files changed, 1081 insertions(+), 901 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
create mode 100644 include/linux/mlx5/eq.h
--
2.19.1
^ permalink raw reply
* [PATCH V2 mlx5-next 02/12] net/mlx5: EQ, Remove unused fields and structures
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
Some fields and structures are not referenced nor used by the driver,
remove them.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 11 -----------
include/linux/mlx5/driver.h | 3 ---
2 files changed, 14 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index aeab0c4f60f4..fd5926daa0a6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -78,17 +78,6 @@ enum {
(1ull << MLX5_EVENT_TYPE_SRQ_LAST_WQE) | \
(1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT))
-struct map_eq_in {
- u64 mask;
- u32 reserved;
- u32 unmap_eqn;
-};
-
-struct cre_des_eq {
- u8 reserved[15];
- u8 eqn;
-};
-
static int mlx5_cmd_destroy_eq(struct mlx5_core_dev *dev, u8 eqn)
{
u32 out[MLX5_ST_SZ_DW(destroy_eq_out)] = {0};
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 7d4ed995b4ce..15cf6727a62d 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -398,7 +398,6 @@ struct mlx5_eq {
unsigned int irqn;
u8 eqn;
int nent;
- u64 mask;
struct list_head list;
int index;
struct mlx5_rsc_debug *dbg;
@@ -478,8 +477,6 @@ struct mlx5_core_srq {
};
struct mlx5_eq_table {
- void __iomem *update_ci;
- void __iomem *update_arm_ci;
struct list_head comp_eqs_list;
struct mlx5_eq pages_eq;
struct mlx5_eq async_eq;
--
2.19.1
^ permalink raw reply related
* [PATCH V2 mlx5-next 01/12] net/mlx5: EQ, Use the right place to store/read IRQ affinity hint
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
Currently the cpu affinity hint mask for completion EQs is stored and
read from the wrong place, since reading and storing is done from the
same index, there is no actual issue with that, but internal irq_info
for completion EQs stars at MLX5_EQ_VEC_COMP_BASE offset in irq_info
array, this patch changes the code to use the correct offset to store
and read the IRQ affinity hint.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 14 ++++++++------
include/linux/mlx5/driver.h | 2 +-
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 1243edbedc9e..2839c30dd3a0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1760,7 +1760,7 @@ static void mlx5e_close_cq(struct mlx5e_cq *cq)
static int mlx5e_get_cpu(struct mlx5e_priv *priv, int ix)
{
- return cpumask_first(priv->mdev->priv.irq_info[ix].mask);
+ return cpumask_first(priv->mdev->priv.irq_info[ix + MLX5_EQ_VEC_COMP_BASE].mask);
}
static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 28132c7dc05f..d5cea0a36e6a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -640,18 +640,19 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev)
static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
{
struct mlx5_priv *priv = &mdev->priv;
- int irq = pci_irq_vector(mdev->pdev, MLX5_EQ_VEC_COMP_BASE + i);
+ int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
+ int irq = pci_irq_vector(mdev->pdev, vecidx);
- if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
+ if (!zalloc_cpumask_var(&priv->irq_info[vecidx].mask, GFP_KERNEL)) {
mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
return -ENOMEM;
}
cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
- priv->irq_info[i].mask);
+ priv->irq_info[vecidx].mask);
if (IS_ENABLED(CONFIG_SMP) &&
- irq_set_affinity_hint(irq, priv->irq_info[i].mask))
+ irq_set_affinity_hint(irq, priv->irq_info[vecidx].mask))
mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
return 0;
@@ -659,11 +660,12 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
{
+ int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
struct mlx5_priv *priv = &mdev->priv;
- int irq = pci_irq_vector(mdev->pdev, MLX5_EQ_VEC_COMP_BASE + i);
+ int irq = pci_irq_vector(mdev->pdev, vecidx);
irq_set_affinity_hint(irq, NULL);
- free_cpumask_var(priv->irq_info[i].mask);
+ free_cpumask_var(priv->irq_info[vecidx].mask);
}
static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index aa5963b5d38e..7d4ed995b4ce 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -1309,7 +1309,7 @@ enum {
static inline const struct cpumask *
mlx5_get_vector_affinity_hint(struct mlx5_core_dev *dev, int vector)
{
- return dev->priv.irq_info[vector].mask;
+ return dev->priv.irq_info[vector + MLX5_EQ_VEC_COMP_BASE].mask;
}
#endif /* MLX5_DRIVER_H */
--
2.19.1
^ permalink raw reply related
* [PATCH V2 mlx5-next 03/12] net/mlx5: EQ, No need to store eq index as a field
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
eq->index is used only for completion EQs and is assigned to be
the completion eq index, it is used only when traversing the completion
eqs list, and it can be calculated dynamically, thus remove the
eq->index field.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/main.c | 4 ++--
include/linux/mlx5/driver.h | 1 -
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index d5cea0a36e6a..f5e6d375a8cc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -702,10 +702,11 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
struct mlx5_eq_table *table = &dev->priv.eq_table;
struct mlx5_eq *eq, *n;
int err = -ENOENT;
+ int i = 0;
spin_lock(&table->lock);
list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
- if (eq->index == vector) {
+ if (i++ == vector) {
*eqn = eq->eqn;
*irqn = eq->irqn;
err = 0;
@@ -797,7 +798,6 @@ static int alloc_comp_eqs(struct mlx5_core_dev *dev)
goto clean;
}
mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->eqn);
- eq->index = i;
spin_lock(&table->lock);
list_add_tail(&eq->list, &table->comp_eqs_list);
spin_unlock(&table->lock);
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 15cf6727a62d..4b62d71825c1 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -399,7 +399,6 @@ struct mlx5_eq {
u8 eqn;
int nent;
struct list_head list;
- int index;
struct mlx5_rsc_debug *dbg;
enum mlx5_eq_type type;
union {
--
2.19.1
^ permalink raw reply related
* [PATCH V2 mlx5-next 04/12] net/mlx5: EQ, Remove redundant completion EQ list lock
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
Completion EQs list is only modified on driver load/unload, locking is
not required, remove it.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 --
drivers/net/ethernet/mellanox/mlx5/core/main.c | 17 +++--------------
include/linux/mlx5/driver.h | 3 ---
3 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index fd5926daa0a6..e75272503027 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -810,8 +810,6 @@ int mlx5_eq_init(struct mlx5_core_dev *dev)
{
int err;
- spin_lock_init(&dev->priv.eq_table.lock);
-
err = mlx5_eq_debugfs_init(dev);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index f5e6d375a8cc..f692c2a42130 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -704,7 +704,6 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
int err = -ENOENT;
int i = 0;
- spin_lock(&table->lock);
list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
if (i++ == vector) {
*eqn = eq->eqn;
@@ -713,7 +712,6 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
break;
}
}
- spin_unlock(&table->lock);
return err;
}
@@ -724,14 +722,11 @@ struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn)
struct mlx5_eq_table *table = &dev->priv.eq_table;
struct mlx5_eq *eq;
- spin_lock(&table->lock);
- list_for_each_entry(eq, &table->comp_eqs_list, list)
- if (eq->eqn == eqn) {
- spin_unlock(&table->lock);
+ list_for_each_entry(eq, &table->comp_eqs_list, list) {
+ if (eq->eqn == eqn)
return eq;
- }
+ }
- spin_unlock(&table->lock);
return ERR_PTR(-ENOENT);
}
@@ -747,17 +742,13 @@ static void free_comp_eqs(struct mlx5_core_dev *dev)
dev->rmap = NULL;
}
#endif
- spin_lock(&table->lock);
list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
list_del(&eq->list);
- spin_unlock(&table->lock);
if (mlx5_destroy_unmap_eq(dev, eq))
mlx5_core_warn(dev, "failed to destroy EQ 0x%x\n",
eq->eqn);
kfree(eq);
- spin_lock(&table->lock);
}
- spin_unlock(&table->lock);
}
static int alloc_comp_eqs(struct mlx5_core_dev *dev)
@@ -798,9 +789,7 @@ static int alloc_comp_eqs(struct mlx5_core_dev *dev)
goto clean;
}
mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->eqn);
- spin_lock(&table->lock);
list_add_tail(&eq->list, &table->comp_eqs_list);
- spin_unlock(&table->lock);
}
return 0;
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 4b62d71825c1..852e397c7624 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -484,9 +484,6 @@ struct mlx5_eq_table {
struct mlx5_eq pfault_eq;
#endif
int num_comp_vectors;
- /* protect EQs list
- */
- spinlock_t lock;
};
struct mlx5_uars_page {
--
2.19.1
^ permalink raw reply related
* [PATCH V2 mlx5-next 06/12] net/mlx5: EQ, Create all EQs in one place
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
Instead of creating the EQ table in three steps at driver load,
- allocate irq vectors
- allocate async EQs
- allocate completion EQs
Gather all of the procedures into one function in eq.c and call it from
driver load.
This will help us reduce the EQ and EQ table private structures
visibility to eq.c in downstream refactoring.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/debugfs.c | 10 ++
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 121 ++++++++++++++----
.../net/ethernet/mellanox/mlx5/core/main.c | 81 ++----------
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 8 +-
4 files changed, 116 insertions(+), 104 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
index 90fabd612b6c..b76766fb6c67 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
@@ -349,6 +349,16 @@ static u64 qp_read_field(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp,
return param;
}
+static int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
+ u32 *out, int outlen)
+{
+ u32 in[MLX5_ST_SZ_DW(query_eq_in)] = {};
+
+ MLX5_SET(query_eq_in, in, opcode, MLX5_CMD_OP_QUERY_EQ);
+ MLX5_SET(query_eq_in, in, eq_number, eq->eqn);
+ return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
+}
+
static u64 eq_read_field(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
int index)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 4d79a4ccb758..44ccd4206104 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -822,7 +822,7 @@ void mlx5_eq_cleanup(struct mlx5_core_dev *dev)
/* Async EQs */
-int mlx5_start_eqs(struct mlx5_core_dev *dev)
+static int create_async_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
u64 async_event_mask = MLX5_ASYNC_EVENT_MASK;
@@ -914,7 +914,7 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
return err;
}
-void mlx5_stop_eqs(struct mlx5_core_dev *dev)
+static void destroy_async_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
int err;
@@ -945,19 +945,9 @@ void mlx5_stop_eqs(struct mlx5_core_dev *dev)
err);
}
-int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
- u32 *out, int outlen)
-{
- u32 in[MLX5_ST_SZ_DW(query_eq_in)] = {0};
-
- MLX5_SET(query_eq_in, in, opcode, MLX5_CMD_OP_QUERY_EQ);
- MLX5_SET(query_eq_in, in, eq_number, eq->eqn);
- return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
-}
-
/* Completion EQs */
-static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
+static int set_comp_irq_affinity_hint(struct mlx5_core_dev *mdev, int i)
{
struct mlx5_priv *priv = &mdev->priv;
int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
@@ -978,7 +968,7 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
return 0;
}
-static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
+static void clear_comp_irq_affinity_hint(struct mlx5_core_dev *mdev, int i)
{
int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
struct mlx5_priv *priv = &mdev->priv;
@@ -988,13 +978,13 @@ static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
free_cpumask_var(priv->irq_info[vecidx].mask);
}
-static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
+static int set_comp_irq_affinity_hints(struct mlx5_core_dev *mdev)
{
int err;
int i;
for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++) {
- err = mlx5_irq_set_affinity_hint(mdev, i);
+ err = set_comp_irq_affinity_hint(mdev, i);
if (err)
goto err_out;
}
@@ -1003,25 +993,25 @@ static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
err_out:
for (i--; i >= 0; i--)
- mlx5_irq_clear_affinity_hint(mdev, i);
+ clear_comp_irq_affinity_hint(mdev, i);
return err;
}
-static void mlx5_irq_clear_affinity_hints(struct mlx5_core_dev *mdev)
+static void clear_comp_irqs_affinity_hints(struct mlx5_core_dev *mdev)
{
int i;
for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++)
- mlx5_irq_clear_affinity_hint(mdev, i);
+ clear_comp_irq_affinity_hint(mdev, i);
}
-void mlx5_free_comp_eqs(struct mlx5_core_dev *dev)
+static void destroy_comp_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
struct mlx5_eq *eq, *n;
- mlx5_irq_clear_affinity_hints(dev);
+ clear_comp_irqs_affinity_hints(dev);
#ifdef CONFIG_RFS_ACCEL
if (dev->rmap) {
@@ -1038,7 +1028,7 @@ void mlx5_free_comp_eqs(struct mlx5_core_dev *dev)
}
}
-int mlx5_alloc_comp_eqs(struct mlx5_core_dev *dev)
+static int create_comp_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
char name[MLX5_MAX_IRQ_NAME];
@@ -1080,7 +1070,7 @@ int mlx5_alloc_comp_eqs(struct mlx5_core_dev *dev)
list_add_tail(&eq->list, &table->comp_eqs_list);
}
- err = mlx5_irq_set_affinity_hints(dev);
+ err = set_comp_irq_affinity_hints(dev);
if (err) {
mlx5_core_err(dev, "Failed to alloc affinity hint cpumask\n");
goto clean;
@@ -1089,7 +1079,7 @@ int mlx5_alloc_comp_eqs(struct mlx5_core_dev *dev)
return 0;
clean:
- mlx5_free_comp_eqs(dev);
+ destroy_comp_eqs(dev);
return err;
}
@@ -1133,7 +1123,7 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
struct mlx5_eq_table *table = &dev->priv.eq_table;
struct mlx5_eq *eq;
- mlx5_irq_clear_affinity_hints(dev);
+ clear_comp_irqs_affinity_hints(dev);
#ifdef CONFIG_RFS_ACCEL
if (dev->rmap) {
@@ -1153,3 +1143,84 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
#endif
pci_free_irq_vectors(dev->pdev);
}
+
+static int alloc_irq_vectors(struct mlx5_core_dev *dev)
+{
+ struct mlx5_priv *priv = &dev->priv;
+ struct mlx5_eq_table *table = &priv->eq_table;
+ int num_eqs = MLX5_CAP_GEN(dev, max_num_eqs) ?
+ MLX5_CAP_GEN(dev, max_num_eqs) :
+ 1 << MLX5_CAP_GEN(dev, log_max_eq);
+ int nvec;
+ int err;
+
+ nvec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() +
+ MLX5_EQ_VEC_COMP_BASE;
+ nvec = min_t(int, nvec, num_eqs);
+ if (nvec <= MLX5_EQ_VEC_COMP_BASE)
+ return -ENOMEM;
+
+ priv->irq_info = kcalloc(nvec, sizeof(*priv->irq_info), GFP_KERNEL);
+ if (!priv->irq_info)
+ return -ENOMEM;
+
+ nvec = pci_alloc_irq_vectors(dev->pdev, MLX5_EQ_VEC_COMP_BASE + 1,
+ nvec, PCI_IRQ_MSIX);
+ if (nvec < 0) {
+ err = nvec;
+ goto err_free_irq_info;
+ }
+
+ table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
+
+ return 0;
+
+err_free_irq_info:
+ kfree(priv->irq_info);
+ return err;
+}
+
+static void free_irq_vectors(struct mlx5_core_dev *dev)
+{
+ struct mlx5_priv *priv = &dev->priv;
+
+ pci_free_irq_vectors(dev->pdev);
+ kfree(priv->irq_info);
+}
+
+int mlx5_eq_table_create(struct mlx5_core_dev *dev)
+{
+ int err;
+
+ err = alloc_irq_vectors(dev);
+ if (err) {
+ mlx5_core_err(dev, "alloc irq vectors failed\n");
+ return err;
+ }
+
+ err = create_async_eqs(dev);
+ if (err) {
+ mlx5_core_err(dev, "Failed to create async EQs\n");
+ goto err_async_eqs;
+ }
+
+ err = create_comp_eqs(dev);
+ if (err) {
+ mlx5_core_err(dev, "Failed to create completion EQs\n");
+ goto err_comp_eqs;
+ }
+
+ return 0;
+err_comp_eqs:
+ destroy_async_eqs(dev);
+err_async_eqs:
+ free_irq_vectors(dev);
+ return err;
+}
+
+void mlx5_eq_table_destroy(struct mlx5_core_dev *dev)
+{
+ destroy_comp_eqs(dev);
+ destroy_async_eqs(dev);
+ free_irq_vectors(dev);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 244fec4b2ef2..21cc9bbc2563 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -319,51 +319,6 @@ static void release_bar(struct pci_dev *pdev)
pci_release_regions(pdev);
}
-static int mlx5_alloc_irq_vectors(struct mlx5_core_dev *dev)
-{
- struct mlx5_priv *priv = &dev->priv;
- struct mlx5_eq_table *table = &priv->eq_table;
- int num_eqs = MLX5_CAP_GEN(dev, max_num_eqs) ?
- MLX5_CAP_GEN(dev, max_num_eqs) :
- 1 << MLX5_CAP_GEN(dev, log_max_eq);
- int nvec;
- int err;
-
- nvec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() +
- MLX5_EQ_VEC_COMP_BASE;
- nvec = min_t(int, nvec, num_eqs);
- if (nvec <= MLX5_EQ_VEC_COMP_BASE)
- return -ENOMEM;
-
- priv->irq_info = kcalloc(nvec, sizeof(*priv->irq_info), GFP_KERNEL);
- if (!priv->irq_info)
- return -ENOMEM;
-
- nvec = pci_alloc_irq_vectors(dev->pdev,
- MLX5_EQ_VEC_COMP_BASE + 1, nvec,
- PCI_IRQ_MSIX);
- if (nvec < 0) {
- err = nvec;
- goto err_free_irq_info;
- }
-
- table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
-
- return 0;
-
-err_free_irq_info:
- kfree(priv->irq_info);
- return err;
-}
-
-static void mlx5_free_irq_vectors(struct mlx5_core_dev *dev)
-{
- struct mlx5_priv *priv = &dev->priv;
-
- pci_free_irq_vectors(dev->pdev);
- kfree(priv->irq_info);
-}
-
struct mlx5_reg_host_endianness {
u8 he;
u8 rsvd[15];
@@ -990,23 +945,17 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
}
}
- err = mlx5_alloc_irq_vectors(dev);
- if (err) {
- dev_err(&pdev->dev, "alloc irq vectors failed\n");
- goto err_cleanup_once;
- }
-
dev->priv.uar = mlx5_get_uars_page(dev);
if (IS_ERR(dev->priv.uar)) {
dev_err(&pdev->dev, "Failed allocating uar, aborting\n");
err = PTR_ERR(dev->priv.uar);
- goto err_disable_msix;
+ goto err_get_uars;
}
- err = mlx5_start_eqs(dev);
+ err = mlx5_eq_table_create(dev);
if (err) {
- dev_err(&pdev->dev, "Failed to start pages and async EQs\n");
- goto err_put_uars;
+ dev_err(&pdev->dev, "Failed to create EQs\n");
+ goto err_eq_table;
}
err = mlx5_fw_tracer_init(dev->tracer);
@@ -1015,12 +964,6 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto err_fw_tracer;
}
- err = mlx5_alloc_comp_eqs(dev);
- if (err) {
- dev_err(&pdev->dev, "Failed to alloc completion EQs\n");
- goto err_comp_eqs;
- }
-
err = mlx5_fpga_device_start(dev);
if (err) {
dev_err(&pdev->dev, "fpga device start failed %d\n", err);
@@ -1089,21 +1032,15 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
mlx5_fpga_device_stop(dev);
err_fpga_start:
- mlx5_free_comp_eqs(dev);
-
-err_comp_eqs:
mlx5_fw_tracer_cleanup(dev->tracer);
err_fw_tracer:
- mlx5_stop_eqs(dev);
+ mlx5_eq_table_destroy(dev);
-err_put_uars:
+err_eq_table:
mlx5_put_uars_page(dev, priv->uar);
-err_disable_msix:
- mlx5_free_irq_vectors(dev);
-
-err_cleanup_once:
+err_get_uars:
if (boot)
mlx5_cleanup_once(dev);
@@ -1160,11 +1097,9 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
mlx5_accel_ipsec_cleanup(dev);
mlx5_accel_tls_cleanup(dev);
mlx5_fpga_device_stop(dev);
- mlx5_free_comp_eqs(dev);
mlx5_fw_tracer_cleanup(dev->tracer);
- mlx5_stop_eqs(dev);
+ mlx5_eq_table_destroy(dev);
mlx5_put_uars_page(dev, priv->uar);
- mlx5_free_irq_vectors(dev);
if (cleanup)
mlx5_cleanup_once(dev);
mlx5_stop_health_poll(dev, cleanup);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 22cff00faa5a..3fa6d26875fe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -132,12 +132,8 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq);
int mlx5_eq_add_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq);
int mlx5_eq_del_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq);
-int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
- u32 *out, int outlen);
-int mlx5_start_eqs(struct mlx5_core_dev *dev);
-void mlx5_stop_eqs(struct mlx5_core_dev *dev);
-int mlx5_alloc_comp_eqs(struct mlx5_core_dev *dev);
-void mlx5_free_comp_eqs(struct mlx5_core_dev *dev);
+int mlx5_eq_table_create(struct mlx5_core_dev *dev);
+void mlx5_eq_table_destroy(struct mlx5_core_dev *dev);
/* This function should only be called after mlx5_cmd_force_teardown_hca */
void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev);
struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn);
--
2.19.1
^ permalink raw reply related
* [PATCH V2 mlx5-next 05/12] net/mlx5: EQ, Move all EQ logic to eq.c
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
Move completion EQs flows from main.c to eq.c, reasons:
1) It is where this logic belongs.
2) It will help centralize the EQ logic in one file for downstream
refactoring, and future extensions/updates.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 176 +++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/main.c | 179 +-----------------
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +
3 files changed, 181 insertions(+), 176 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index e75272503027..4d79a4ccb758 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -820,6 +820,8 @@ void mlx5_eq_cleanup(struct mlx5_core_dev *dev)
mlx5_eq_debugfs_cleanup(dev);
}
+/* Async EQs */
+
int mlx5_start_eqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
@@ -953,12 +955,186 @@ int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
}
+/* Completion EQs */
+
+static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
+{
+ struct mlx5_priv *priv = &mdev->priv;
+ int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
+ int irq = pci_irq_vector(mdev->pdev, vecidx);
+
+ if (!zalloc_cpumask_var(&priv->irq_info[vecidx].mask, GFP_KERNEL)) {
+ mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
+ return -ENOMEM;
+ }
+
+ cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
+ priv->irq_info[vecidx].mask);
+
+ if (IS_ENABLED(CONFIG_SMP) &&
+ irq_set_affinity_hint(irq, priv->irq_info[vecidx].mask))
+ mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
+
+ return 0;
+}
+
+static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
+{
+ int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
+ struct mlx5_priv *priv = &mdev->priv;
+ int irq = pci_irq_vector(mdev->pdev, vecidx);
+
+ irq_set_affinity_hint(irq, NULL);
+ free_cpumask_var(priv->irq_info[vecidx].mask);
+}
+
+static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
+{
+ int err;
+ int i;
+
+ for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++) {
+ err = mlx5_irq_set_affinity_hint(mdev, i);
+ if (err)
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ for (i--; i >= 0; i--)
+ mlx5_irq_clear_affinity_hint(mdev, i);
+
+ return err;
+}
+
+static void mlx5_irq_clear_affinity_hints(struct mlx5_core_dev *mdev)
+{
+ int i;
+
+ for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++)
+ mlx5_irq_clear_affinity_hint(mdev, i);
+}
+
+void mlx5_free_comp_eqs(struct mlx5_core_dev *dev)
+{
+ struct mlx5_eq_table *table = &dev->priv.eq_table;
+ struct mlx5_eq *eq, *n;
+
+ mlx5_irq_clear_affinity_hints(dev);
+
+#ifdef CONFIG_RFS_ACCEL
+ if (dev->rmap) {
+ free_irq_cpu_rmap(dev->rmap);
+ dev->rmap = NULL;
+ }
+#endif
+ list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
+ list_del(&eq->list);
+ if (mlx5_destroy_unmap_eq(dev, eq))
+ mlx5_core_warn(dev, "failed to destroy EQ 0x%x\n",
+ eq->eqn);
+ kfree(eq);
+ }
+}
+
+int mlx5_alloc_comp_eqs(struct mlx5_core_dev *dev)
+{
+ struct mlx5_eq_table *table = &dev->priv.eq_table;
+ char name[MLX5_MAX_IRQ_NAME];
+ struct mlx5_eq *eq;
+ int ncomp_vec;
+ int nent;
+ int err;
+ int i;
+
+ INIT_LIST_HEAD(&table->comp_eqs_list);
+ ncomp_vec = table->num_comp_vectors;
+ nent = MLX5_COMP_EQ_SIZE;
+#ifdef CONFIG_RFS_ACCEL
+ dev->rmap = alloc_irq_cpu_rmap(ncomp_vec);
+ if (!dev->rmap)
+ return -ENOMEM;
+#endif
+ for (i = 0; i < ncomp_vec; i++) {
+ int vecidx = i + MLX5_EQ_VEC_COMP_BASE;
+
+ eq = kzalloc(sizeof(*eq), GFP_KERNEL);
+ if (!eq) {
+ err = -ENOMEM;
+ goto clean;
+ }
+
+#ifdef CONFIG_RFS_ACCEL
+ irq_cpu_rmap_add(dev->rmap, pci_irq_vector(dev->pdev, vecidx));
+#endif
+ snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);
+ err = mlx5_create_map_eq(dev, eq, vecidx, nent, 0,
+ name, MLX5_EQ_TYPE_COMP);
+ if (err) {
+ kfree(eq);
+ goto clean;
+ }
+ mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->eqn);
+ /* add tail, to keep the list ordered, for mlx5_vector2eqn to work */
+ list_add_tail(&eq->list, &table->comp_eqs_list);
+ }
+
+ err = mlx5_irq_set_affinity_hints(dev);
+ if (err) {
+ mlx5_core_err(dev, "Failed to alloc affinity hint cpumask\n");
+ goto clean;
+ }
+
+ return 0;
+
+clean:
+ mlx5_free_comp_eqs(dev);
+ return err;
+}
+
+int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
+ unsigned int *irqn)
+{
+ struct mlx5_eq_table *table = &dev->priv.eq_table;
+ struct mlx5_eq *eq, *n;
+ int err = -ENOENT;
+ int i = 0;
+
+ list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
+ if (i++ == vector) {
+ *eqn = eq->eqn;
+ *irqn = eq->irqn;
+ err = 0;
+ break;
+ }
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(mlx5_vector2eqn);
+
+struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn)
+{
+ struct mlx5_eq_table *table = &dev->priv.eq_table;
+ struct mlx5_eq *eq;
+
+ list_for_each_entry(eq, &table->comp_eqs_list, list) {
+ if (eq->eqn == eqn)
+ return eq;
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
/* This function should only be called after mlx5_cmd_force_teardown_hca */
void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
{
struct mlx5_eq_table *table = &dev->priv.eq_table;
struct mlx5_eq *eq;
+ mlx5_irq_clear_affinity_hints(dev);
+
#ifdef CONFIG_RFS_ACCEL
if (dev->rmap) {
free_irq_cpu_rmap(dev->rmap);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index f692c2a42130..244fec4b2ef2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -637,168 +637,6 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev)
return (u64)timer_l | (u64)timer_h1 << 32;
}
-static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
-{
- struct mlx5_priv *priv = &mdev->priv;
- int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
- int irq = pci_irq_vector(mdev->pdev, vecidx);
-
- if (!zalloc_cpumask_var(&priv->irq_info[vecidx].mask, GFP_KERNEL)) {
- mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
- return -ENOMEM;
- }
-
- cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
- priv->irq_info[vecidx].mask);
-
- if (IS_ENABLED(CONFIG_SMP) &&
- irq_set_affinity_hint(irq, priv->irq_info[vecidx].mask))
- mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
-
- return 0;
-}
-
-static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
-{
- int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
- struct mlx5_priv *priv = &mdev->priv;
- int irq = pci_irq_vector(mdev->pdev, vecidx);
-
- irq_set_affinity_hint(irq, NULL);
- free_cpumask_var(priv->irq_info[vecidx].mask);
-}
-
-static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
-{
- int err;
- int i;
-
- for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++) {
- err = mlx5_irq_set_affinity_hint(mdev, i);
- if (err)
- goto err_out;
- }
-
- return 0;
-
-err_out:
- for (i--; i >= 0; i--)
- mlx5_irq_clear_affinity_hint(mdev, i);
-
- return err;
-}
-
-static void mlx5_irq_clear_affinity_hints(struct mlx5_core_dev *mdev)
-{
- int i;
-
- for (i = 0; i < mdev->priv.eq_table.num_comp_vectors; i++)
- mlx5_irq_clear_affinity_hint(mdev, i);
-}
-
-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
- unsigned int *irqn)
-{
- struct mlx5_eq_table *table = &dev->priv.eq_table;
- struct mlx5_eq *eq, *n;
- int err = -ENOENT;
- int i = 0;
-
- list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
- if (i++ == vector) {
- *eqn = eq->eqn;
- *irqn = eq->irqn;
- err = 0;
- break;
- }
- }
-
- return err;
-}
-EXPORT_SYMBOL(mlx5_vector2eqn);
-
-struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn)
-{
- struct mlx5_eq_table *table = &dev->priv.eq_table;
- struct mlx5_eq *eq;
-
- list_for_each_entry(eq, &table->comp_eqs_list, list) {
- if (eq->eqn == eqn)
- return eq;
- }
-
-
- return ERR_PTR(-ENOENT);
-}
-
-static void free_comp_eqs(struct mlx5_core_dev *dev)
-{
- struct mlx5_eq_table *table = &dev->priv.eq_table;
- struct mlx5_eq *eq, *n;
-
-#ifdef CONFIG_RFS_ACCEL
- if (dev->rmap) {
- free_irq_cpu_rmap(dev->rmap);
- dev->rmap = NULL;
- }
-#endif
- list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
- list_del(&eq->list);
- if (mlx5_destroy_unmap_eq(dev, eq))
- mlx5_core_warn(dev, "failed to destroy EQ 0x%x\n",
- eq->eqn);
- kfree(eq);
- }
-}
-
-static int alloc_comp_eqs(struct mlx5_core_dev *dev)
-{
- struct mlx5_eq_table *table = &dev->priv.eq_table;
- char name[MLX5_MAX_IRQ_NAME];
- struct mlx5_eq *eq;
- int ncomp_vec;
- int nent;
- int err;
- int i;
-
- INIT_LIST_HEAD(&table->comp_eqs_list);
- ncomp_vec = table->num_comp_vectors;
- nent = MLX5_COMP_EQ_SIZE;
-#ifdef CONFIG_RFS_ACCEL
- dev->rmap = alloc_irq_cpu_rmap(ncomp_vec);
- if (!dev->rmap)
- return -ENOMEM;
-#endif
- for (i = 0; i < ncomp_vec; i++) {
- eq = kzalloc(sizeof(*eq), GFP_KERNEL);
- if (!eq) {
- err = -ENOMEM;
- goto clean;
- }
-
-#ifdef CONFIG_RFS_ACCEL
- irq_cpu_rmap_add(dev->rmap, pci_irq_vector(dev->pdev,
- MLX5_EQ_VEC_COMP_BASE + i));
-#endif
- snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);
- err = mlx5_create_map_eq(dev, eq,
- i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
- name, MLX5_EQ_TYPE_COMP);
- if (err) {
- kfree(eq);
- goto clean;
- }
- mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->eqn);
- list_add_tail(&eq->list, &table->comp_eqs_list);
- }
-
- return 0;
-
-clean:
- free_comp_eqs(dev);
- return err;
-}
-
static int mlx5_core_set_issi(struct mlx5_core_dev *dev)
{
u32 query_in[MLX5_ST_SZ_DW(query_issi_in)] = {0};
@@ -1177,18 +1015,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
goto err_fw_tracer;
}
- err = alloc_comp_eqs(dev);
+ err = mlx5_alloc_comp_eqs(dev);
if (err) {
dev_err(&pdev->dev, "Failed to alloc completion EQs\n");
goto err_comp_eqs;
}
- err = mlx5_irq_set_affinity_hints(dev);
- if (err) {
- dev_err(&pdev->dev, "Failed to alloc affinity hint cpumask\n");
- goto err_affinity_hints;
- }
-
err = mlx5_fpga_device_start(dev);
if (err) {
dev_err(&pdev->dev, "fpga device start failed %d\n", err);
@@ -1257,10 +1089,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
mlx5_fpga_device_stop(dev);
err_fpga_start:
- mlx5_irq_clear_affinity_hints(dev);
-
-err_affinity_hints:
- free_comp_eqs(dev);
+ mlx5_free_comp_eqs(dev);
err_comp_eqs:
mlx5_fw_tracer_cleanup(dev->tracer);
@@ -1331,8 +1160,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
mlx5_accel_ipsec_cleanup(dev);
mlx5_accel_tls_cleanup(dev);
mlx5_fpga_device_stop(dev);
- mlx5_irq_clear_affinity_hints(dev);
- free_comp_eqs(dev);
+ mlx5_free_comp_eqs(dev);
mlx5_fw_tracer_cleanup(dev->tracer);
mlx5_stop_eqs(dev);
mlx5_put_uars_page(dev, priv->uar);
@@ -1628,7 +1456,6 @@ static int mlx5_try_fast_unload(struct mlx5_core_dev *dev)
* kexec. There is no need to cleanup the mlx5_core software
* contexts.
*/
- mlx5_irq_clear_affinity_hints(dev);
mlx5_core_eq_free_irqs(dev);
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 0594d0961cb3..22cff00faa5a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -136,6 +136,8 @@ int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
u32 *out, int outlen);
int mlx5_start_eqs(struct mlx5_core_dev *dev);
void mlx5_stop_eqs(struct mlx5_core_dev *dev);
+int mlx5_alloc_comp_eqs(struct mlx5_core_dev *dev);
+void mlx5_free_comp_eqs(struct mlx5_core_dev *dev);
/* This function should only be called after mlx5_cmd_force_teardown_hca */
void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev);
struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn);
--
2.19.1
^ permalink raw reply related
* [PATCH V2 mlx5-next 07/12] net/mlx5: EQ, irq_info and rmap belong to eq_table
From: Saeed Mahameed @ 2018-11-19 18:52 UTC (permalink / raw)
To: Leon Romanovsky, saeedm; +Cc: netdev, linux-rdma, Jason Gunthorpe
In-Reply-To: <20181119185242.21961-1-saeedm@mellanox.com>
irq_info and rmap are EQ properties of the driver, and only needed for
EQ objects, move them to the eq_table EQs database structure.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/en_main.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 40 ++++++++++---------
include/linux/mlx5/driver.h | 10 ++---
3 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 2839c30dd3a0..32ea47c28324 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1760,7 +1760,7 @@ static void mlx5e_close_cq(struct mlx5e_cq *cq)
static int mlx5e_get_cpu(struct mlx5e_priv *priv, int ix)
{
- return cpumask_first(priv->mdev->priv.irq_info[ix + MLX5_EQ_VEC_COMP_BASE].mask);
+ return cpumask_first(priv->mdev->priv.eq_table.irq_info[ix + MLX5_EQ_VEC_COMP_BASE].mask);
}
static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
@@ -4960,7 +4960,7 @@ int mlx5e_netdev_init(struct net_device *netdev,
netif_carrier_off(netdev);
#ifdef CONFIG_MLX5_EN_ARFS
- netdev->rx_cpu_rmap = mdev->rmap;
+ netdev->rx_cpu_rmap = mdev->priv.eq_table.rmap;
#endif
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 44ccd4206104..70f62f10065e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -694,7 +694,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
if (err)
goto err_in;
- snprintf(priv->irq_info[vecidx].name, MLX5_MAX_IRQ_NAME, "%s@pci:%s",
+ snprintf(priv->eq_table.irq_info[vecidx].name, MLX5_MAX_IRQ_NAME, "%s@pci:%s",
name, pci_name(dev->pdev));
eq->eqn = MLX5_GET(create_eq_out, out, eq_number);
@@ -702,7 +702,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
eq->dev = dev;
eq->doorbell = priv->uar->map + MLX5_EQ_DOORBEL_OFFSET;
err = request_irq(eq->irqn, handler, 0,
- priv->irq_info[vecidx].name, eq);
+ priv->eq_table.irq_info[vecidx].name, eq);
if (err)
goto err_eq;
@@ -952,17 +952,18 @@ static int set_comp_irq_affinity_hint(struct mlx5_core_dev *mdev, int i)
struct mlx5_priv *priv = &mdev->priv;
int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
int irq = pci_irq_vector(mdev->pdev, vecidx);
+ struct mlx5_irq_info *irq_info = &priv->eq_table.irq_info[vecidx];
- if (!zalloc_cpumask_var(&priv->irq_info[vecidx].mask, GFP_KERNEL)) {
+ if (!zalloc_cpumask_var(&irq_info->mask, GFP_KERNEL)) {
mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
return -ENOMEM;
}
cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
- priv->irq_info[vecidx].mask);
+ irq_info->mask);
if (IS_ENABLED(CONFIG_SMP) &&
- irq_set_affinity_hint(irq, priv->irq_info[vecidx].mask))
+ irq_set_affinity_hint(irq, irq_info->mask))
mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
return 0;
@@ -973,9 +974,10 @@ static void clear_comp_irq_affinity_hint(struct mlx5_core_dev *mdev, int i)
int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
struct mlx5_priv *priv = &mdev->priv;
int irq = pci_irq_vector(mdev->pdev, vecidx);
+ struct mlx5_irq_info *irq_info = &priv->eq_table.irq_info[vecidx];
irq_set_affinity_hint(irq, NULL);
- free_cpumask_var(priv->irq_info[vecidx].mask);
+ free_cpumask_var(irq_info->mask);
}
static int set_comp_irq_affinity_hints(struct mlx5_core_dev *mdev)
@@ -1014,9 +1016,9 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev)
clear_comp_irqs_affinity_hints(dev);
#ifdef CONFIG_RFS_ACCEL
- if (dev->rmap) {
- free_irq_cpu_rmap(dev->rmap);
- dev->rmap = NULL;
+ if (table->rmap) {
+ free_irq_cpu_rmap(table->rmap);
+ table->rmap = NULL;
}
#endif
list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
@@ -1042,8 +1044,8 @@ static int create_comp_eqs(struct mlx5_core_dev *dev)
ncomp_vec = table->num_comp_vectors;
nent = MLX5_COMP_EQ_SIZE;
#ifdef CONFIG_RFS_ACCEL
- dev->rmap = alloc_irq_cpu_rmap(ncomp_vec);
- if (!dev->rmap)
+ table->rmap = alloc_irq_cpu_rmap(ncomp_vec);
+ if (!table->rmap)
return -ENOMEM;
#endif
for (i = 0; i < ncomp_vec; i++) {
@@ -1056,7 +1058,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev)
}
#ifdef CONFIG_RFS_ACCEL
- irq_cpu_rmap_add(dev->rmap, pci_irq_vector(dev->pdev, vecidx));
+ irq_cpu_rmap_add(table->rmap, pci_irq_vector(dev->pdev, vecidx));
#endif
snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", i);
err = mlx5_create_map_eq(dev, eq, vecidx, nent, 0,
@@ -1126,9 +1128,9 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
clear_comp_irqs_affinity_hints(dev);
#ifdef CONFIG_RFS_ACCEL
- if (dev->rmap) {
- free_irq_cpu_rmap(dev->rmap);
- dev->rmap = NULL;
+ if (table->rmap) {
+ free_irq_cpu_rmap(table->rmap);
+ table->rmap = NULL;
}
#endif
list_for_each_entry(eq, &table->comp_eqs_list, list)
@@ -1160,8 +1162,8 @@ static int alloc_irq_vectors(struct mlx5_core_dev *dev)
if (nvec <= MLX5_EQ_VEC_COMP_BASE)
return -ENOMEM;
- priv->irq_info = kcalloc(nvec, sizeof(*priv->irq_info), GFP_KERNEL);
- if (!priv->irq_info)
+ table->irq_info = kcalloc(nvec, sizeof(*table->irq_info), GFP_KERNEL);
+ if (!table->irq_info)
return -ENOMEM;
nvec = pci_alloc_irq_vectors(dev->pdev, MLX5_EQ_VEC_COMP_BASE + 1,
@@ -1176,7 +1178,7 @@ static int alloc_irq_vectors(struct mlx5_core_dev *dev)
return 0;
err_free_irq_info:
- kfree(priv->irq_info);
+ kfree(table->irq_info);
return err;
}
@@ -1185,7 +1187,7 @@ static void free_irq_vectors(struct mlx5_core_dev *dev)
struct mlx5_priv *priv = &dev->priv;
pci_free_irq_vectors(dev->pdev);
- kfree(priv->irq_info);
+ kfree(priv->eq_table.irq_info);
}
int mlx5_eq_table_create(struct mlx5_core_dev *dev)
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 852e397c7624..dcc3f7aa8572 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -484,6 +484,10 @@ struct mlx5_eq_table {
struct mlx5_eq pfault_eq;
#endif
int num_comp_vectors;
+ struct mlx5_irq_info *irq_info;
+#ifdef CONFIG_RFS_ACCEL
+ struct cpu_rmap *rmap;
+#endif
};
struct mlx5_uars_page {
@@ -640,7 +644,6 @@ struct mlx5_port_module_event_stats {
struct mlx5_priv {
char name[MLX5_MAX_NAME_LEN];
struct mlx5_eq_table eq_table;
- struct mlx5_irq_info *irq_info;
/* pages stuff */
struct workqueue_struct *pg_wq;
@@ -851,9 +854,6 @@ struct mlx5_core_dev {
} roce;
#ifdef CONFIG_MLX5_FPGA
struct mlx5_fpga_device *fpga;
-#endif
-#ifdef CONFIG_RFS_ACCEL
- struct cpu_rmap *rmap;
#endif
struct mlx5_clock clock;
struct mlx5_ib_clock_info *clock_info;
@@ -1302,7 +1302,7 @@ enum {
static inline const struct cpumask *
mlx5_get_vector_affinity_hint(struct mlx5_core_dev *dev, int vector)
{
- return dev->priv.irq_info[vector + MLX5_EQ_VEC_COMP_BASE].mask;
+ return dev->priv.eq_table.irq_info[vector + MLX5_EQ_VEC_COMP_BASE].mask;
}
#endif /* MLX5_DRIVER_H */
--
2.19.1
^ permalink raw reply related
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