* [PATCH net-next v5 0/2] openvswitch: Support conntrack zone limit
From: Yi-Hung Wei @ 2018-05-25 0:56 UTC (permalink / raw)
To: netdev, pshelar; +Cc: Yi-Hung Wei
Currently, nf_conntrack_max is used to limit the maximum number of
conntrack entries in the conntrack table for every network namespace.
For the VMs and containers that reside in the same namespace,
they share the same conntrack table, and the total # of conntrack entries
for all the VMs and containers are limited by nf_conntrack_max. In this
case, if one of the VM/container abuses the usage the conntrack entries,
it blocks the others from committing valid conntrack entries into the
conntrack table. Even if we can possibly put the VM in different network
namespace, the current nf_conntrack_max configuration is kind of rigid
that we cannot limit different VM/container to have different # conntrack
entries.
To address the aforementioned issue, this patch proposes to have a
fine-grained mechanism that could further limit the # of conntrack entries
per-zone. For example, we can designate different zone to different VM,
and set conntrack limit to each zone. By providing this isolation, a
mis-behaved VM only consumes the conntrack entries in its own zone, and
it will not influence other well-behaved VMs. Moreover, the users can
set various conntrack limit to different zone based on their preference.
The proposed implementation utilizes Netfilter's nf_conncount backend
to count the number of connections in a particular zone. If the number of
connection is above a configured limitation, OVS will return ENOMEM to the
userspace. If userspace does not configure the zone limit, the limit
defaults to zero that is no limitation, which is backward compatible to
the behavior without this patch.
The first patch defines the conntrack limit netlink definition, and the
second patch provides the implementation.
v4->v5:
- Addresses comments from Parvin that include log error msg in
ovs_ct_limit_init(), handle deletion for default limit, and
add a common helper for get zone limit.
- Rebases to master.
v3->v4:
- Addresses comments from Parvin that include simplify netlink API,
and remove unncessary RCU lockings.
- Rebases to master.
v2->v3:
- Addresses comments from Parvin that include using static keys to check
if ovs_ct_limit features is used, only check ct_limit when a ct entry
is unconfirmed, and reports rate limited warning messages when the ct
limit is reached.
- Rebases to master.
v1->v2:
- Fixes commit log typos suggested by Greg.
- Fixes memory free issue that Julia found.
Yi-Hung Wei (2):
openvswitch: Add conntrack limit netlink definition
openvswitch: Support conntrack zone limit
include/uapi/linux/openvswitch.h | 28 ++
net/openvswitch/Kconfig | 3 +-
net/openvswitch/conntrack.c | 551 ++++++++++++++++++++++++++++++++++++++-
net/openvswitch/conntrack.h | 9 +-
net/openvswitch/datapath.c | 7 +-
net/openvswitch/datapath.h | 3 +
6 files changed, 595 insertions(+), 6 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [Bridge] [PATCH net-next] net: bridge: add support for port isolation
From: Toshiaki Makita @ 2018-05-25 0:47 UTC (permalink / raw)
To: Nikolay Aleksandrov, netdev; +Cc: roopa, bridge, davem
In-Reply-To: <20180524085648.5934-1-nikolay@cumulusnetworks.com>
On 2018/05/24 17:56, Nikolay Aleksandrov wrote:
> This patch adds support for a new port flag - BR_ISOLATED. If it is set
> then isolated ports cannot communicate between each other, but they can
> still communicate with non-isolated ports. The same can be achieved via
> ACLs but they can't scale with large number of ports and also the
> complexity of the rules grows. This feature can be used to achieve
> isolated vlan functionality (similar to pvlan) as well, though currently
> it will be port-wide (for all vlans on the port). The new test in
> should_deliver uses data that is already cache hot and the new boolean
> is used to avoid an additional source port test in should_deliver.
>
> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Sometimes I need this kind of configuration and used vlan for such
cases. I guess it does not scale for your case so added this feature.
I wonder if this kind of feature is common in hardware switches.
FWIW,
Reviewed-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
> ---
> include/linux/if_bridge.h | 1 +
> include/uapi/linux/if_link.h | 1 +
> net/bridge/br_forward.c | 3 ++-
> net/bridge/br_input.c | 1 +
> net/bridge/br_netlink.c | 9 ++++++++-
> net/bridge/br_private.h | 9 +++++++++
> net/bridge/br_sysfs_if.c | 2 ++
> 7 files changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index 585d27182425..7843b98e1c6e 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -50,6 +50,7 @@ struct br_ip_list {
> #define BR_VLAN_TUNNEL BIT(13)
> #define BR_BCAST_FLOOD BIT(14)
> #define BR_NEIGH_SUPPRESS BIT(15)
> +#define BR_ISOLATED BIT(16)
>
> #define BR_DEFAULT_AGEING_TIME (300 * HZ)
>
> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> index b85266420bfb..cf01b6824244 100644
> --- a/include/uapi/linux/if_link.h
> +++ b/include/uapi/linux/if_link.h
> @@ -333,6 +333,7 @@ enum {
> IFLA_BRPORT_BCAST_FLOOD,
> IFLA_BRPORT_GROUP_FWD_MASK,
> IFLA_BRPORT_NEIGH_SUPPRESS,
> + IFLA_BRPORT_ISOLATED,
> __IFLA_BRPORT_MAX
> };
> #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
> diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
> index 7a7fd672ccf2..9019f326fe81 100644
> --- a/net/bridge/br_forward.c
> +++ b/net/bridge/br_forward.c
> @@ -30,7 +30,8 @@ static inline int should_deliver(const struct net_bridge_port *p,
> vg = nbp_vlan_group_rcu(p);
> return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
> br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING &&
> - nbp_switchdev_allowed_egress(p, skb);
> + nbp_switchdev_allowed_egress(p, skb) &&
> + !br_skb_isolated(p, skb);
> }
>
> int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> index 7f98a7d25866..72074276c088 100644
> --- a/net/bridge/br_input.c
> +++ b/net/bridge/br_input.c
> @@ -114,6 +114,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
> goto drop;
>
> BR_INPUT_SKB_CB(skb)->brdev = br->dev;
> + BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED);
>
> if (IS_ENABLED(CONFIG_INET) &&
> (skb->protocol == htons(ETH_P_ARP) ||
> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
> index 015f465c514b..9f5eb05b0373 100644
> --- a/net/bridge/br_netlink.c
> +++ b/net/bridge/br_netlink.c
> @@ -139,6 +139,7 @@ static inline size_t br_port_info_size(void)
> + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */
> + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */
> + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */
> + + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */
> + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */
> + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */
> + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */
> @@ -213,7 +214,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
> BR_VLAN_TUNNEL)) ||
> nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) ||
> nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS,
> - !!(p->flags & BR_NEIGH_SUPPRESS)))
> + !!(p->flags & BR_NEIGH_SUPPRESS)) ||
> + nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)))
> return -EMSGSIZE;
>
> timerval = br_timer_value(&p->message_age_timer);
> @@ -660,6 +662,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
> [IFLA_BRPORT_VLAN_TUNNEL] = { .type = NLA_U8 },
> [IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NLA_U16 },
> [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 },
> + [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 },
> };
>
> /* Change the state of the port and notify spanning tree */
> @@ -810,6 +813,10 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
> if (err)
> return err;
>
> + err = br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED);
> + if (err)
> + return err;
> +
> br_port_flags_change(p, old_flags ^ p->flags);
> return 0;
> }
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 742f40aefdaf..11520ed528b0 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -423,6 +423,7 @@ struct br_input_skb_cb {
> #endif
>
> bool proxyarp_replied;
> + bool src_port_isolated;
>
> #ifdef CONFIG_BRIDGE_VLAN_FILTERING
> bool vlan_filtered;
> @@ -574,6 +575,14 @@ int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
> void br_flood(struct net_bridge *br, struct sk_buff *skb,
> enum br_pkt_type pkt_type, bool local_rcv, bool local_orig);
>
> +/* return true if both source port and dest port are isolated */
> +static inline bool br_skb_isolated(const struct net_bridge_port *to,
> + const struct sk_buff *skb)
> +{
> + return BR_INPUT_SKB_CB(skb)->src_port_isolated &&
> + (to->flags & BR_ISOLATED);
> +}
> +
> /* br_if.c */
> void br_port_carrier_check(struct net_bridge_port *p, bool *notified);
> int br_add_bridge(struct net *net, const char *name);
> diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
> index fd31ad83ec7b..f99c5bf5c906 100644
> --- a/net/bridge/br_sysfs_if.c
> +++ b/net/bridge/br_sysfs_if.c
> @@ -192,6 +192,7 @@ BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI);
> BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD);
> BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD);
> BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS);
> +BRPORT_ATTR_FLAG(isolated, BR_ISOLATED);
>
> #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
> static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
> @@ -243,6 +244,7 @@ static const struct brport_attribute *brport_attrs[] = {
> &brport_attr_broadcast_flood,
> &brport_attr_group_fwd_mask,
> &brport_attr_neigh_suppress,
> + &brport_attr_isolated,
> NULL
> };
>
>
--
Toshiaki Makita
^ permalink raw reply
* Re: [PATCH v3 net] stmmac: Added support for 802.1ad S-TAG stripping
From: Toshiaki Makita @ 2018-05-25 0:34 UTC (permalink / raw)
To: Elad Nachman, Jose Abreu, Florian Fainelli, David Miller
Cc: netdev, peppe.cavallaro, alexandre.torgue
In-Reply-To: <c9c605d9-dff6-4909-e90f-e3b7e179edb6@gmail.com>
On 2018/05/25 1:56, Elad Nachman wrote:
> stmmac reception handler calls stmmac_rx_vlan() to strip the vlan before calling napi_gro_receive().
>
> The function assumes VLAN tagged frames are always tagged with 802.1Q protocol,
> and assigns ETH_P_8021Q to the skb by hard-coding the parameter on call to __vlan_hwaccel_put_tag() .
>
> This causes packets not to be passed to the VLAN slave if it was created with 802.1AD protocol
> (ip link add link eth0 eth0.100 type vlan proto 802.1ad id 100).
>
> This fix passes the protocol from the VLAN header into __vlan_hwaccel_put_tag()
> instead of using the hard-coded value of ETH_P_8021Q.
> NETIF_F_HW_VLAN_STAG_RX was added to the net device features to reflect this new support.
>
> Signed-off-by: Elad Nachman <eladn@gilat.com>
>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 +++++++++-------
> 1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index b65e2d1..2d2f37f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3293,17 +3293,19 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>
> static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
> {
> - struct ethhdr *ehdr;
> + struct vlan_ethhdr *veth;
> u16 vlanid;
> + __be16 vlan_proto;
>
> - if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
> - NETIF_F_HW_VLAN_CTAG_RX &&
> + if ((dev->features & (NETIF_F_HW_VLAN_CTAG_RX|NETIF_F_HW_VLAN_STAG_RX)) ==
> + (NETIF_F_HW_VLAN_CTAG_RX|NETIF_F_HW_VLAN_STAG_RX) &&
This is basically not a correct condition since you cannot strip CTAG if
HW_VLAN_STAG_RX is disabled even when HW_VLAN_CTAG_RX is enabled.
The correct behavior is stripping CTAG when CTAG_RX is enabled and
stripping STAG when STAG_RX is enabled, so this code cannot be
protocol-agnostic. I suggested handling only CTAG in this driver because
I thought adding STAG support will make this unnecessarily complicated.
But I now actually noticed that this driver seems not able to toggle
CTAG_RX nor STAG_RX because hw_features does not include them. So this
code should work even if the condition is wrong, but in the first place
why we need to check if dev->features includes CTAG_RX here... it's
always included. It seems removing this check will be sufficient.
> !__vlan_get_tag(skb, &vlanid)) {
> /* pop the vlan tag */
> - ehdr = (struct ethhdr *)skb->data;
> - memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
> + veth = (struct vlan_ethhdr *)skb->data;
> + vlan_proto = veth->h_vlan_proto;
> + memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2);
> skb_pull(skb, VLAN_HLEN);
> - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
> + __vlan_hwaccel_put_tag(skb, vlan_proto, vlanid);
> }
> }
>
> @@ -4344,7 +4346,7 @@ int stmmac_dvr_probe(struct device *device,
> ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
> #ifdef STMMAC_VLAN_TAG_USED
> /* Both mac100 and gmac support receive VLAN tag detection */
> - ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
> + ndev->features |= (NETIF_F_HW_VLAN_CTAG_RX|NETIF_F_HW_VLAN_STAG_RX);
> #endif
> priv->msg_enable = netif_msg_init(debug, default_msg_level);
>
>
--
Toshiaki Makita
^ permalink raw reply
* Re: [PATCH net] vhost: synchronize IOTLB message with dev cleanup
From: Michael S. Tsirkin @ 2018-05-25 0:33 UTC (permalink / raw)
To: Jason Wang; +Cc: kvm, virtualization, netdev, linux-kernel
In-Reply-To: <1526990337-24892-1-git-send-email-jasowang@redhat.com>
On Tue, May 22, 2018 at 07:58:57PM +0800, Jason Wang wrote:
> DaeRyong Jeong reports a race between vhost_dev_cleanup() and
> vhost_process_iotlb_msg():
>
> Thread interleaving:
> CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup)
> (In the case of both VHOST_IOTLB_UPDATE and
> VHOST_IOTLB_INVALIDATE)
> ===== =====
> vhost_umem_clean(dev->iotlb);
> if (!dev->iotlb) {
> ret = -EFAULT;
> break;
> }
> dev->iotlb = NULL;
>
> The reason is we don't synchronize between them, fixing by protecting
> vhost_process_iotlb_msg() with dev mutex.
>
> Reported-by: DaeRyong Jeong <threeearcat@gmail.com>
> Fixes: 6b1e6cc7855b0 ("vhost: new device IOTLB API")
> Signed-off-by: Jason Wang <jasowang@redhat.com>
We should think of a way to have a per-vq lock here, but for now:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> drivers/vhost/vhost.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index f3bd8e9..f0be5f3 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -981,6 +981,7 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
> {
> int ret = 0;
>
> + mutex_lock(&dev->mutex);
> vhost_dev_lock_vqs(dev);
> switch (msg->type) {
> case VHOST_IOTLB_UPDATE:
> @@ -1016,6 +1017,8 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
> }
>
> vhost_dev_unlock_vqs(dev);
> + mutex_unlock(&dev->mutex);
> +
> return ret;
> }
> ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
> --
> 2.7.4
^ permalink raw reply
* Re: [PATCH bpf-next v5 0/7] bpf: implement BPF_TASK_FD_QUERY
From: Daniel Borkmann @ 2018-05-25 0:27 UTC (permalink / raw)
To: Yonghong Song, peterz, ast, netdev; +Cc: kernel-team
In-Reply-To: <20180524182111.454612-1-yhs@fb.com>
On 05/24/2018 08:21 PM, Yonghong Song wrote:
> Currently, suppose a userspace application has loaded a bpf program
> and attached it to a tracepoint/kprobe/uprobe, and a bpf
> introspection tool, e.g., bpftool, wants to show which bpf program
> is attached to which tracepoint/kprobe/uprobe. Such attachment
> information will be really useful to understand the overall bpf
> deployment in the system.
>
> There is a name field (16 bytes) for each program, which could
> be used to encode the attachment point. There are some drawbacks
> for this approaches. First, bpftool user (e.g., an admin) may not
> really understand the association between the name and the
> attachment point. Second, if one program is attached to multiple
> places, encoding a proper name which can imply all these
> attachments becomes difficult.
>
> This patch introduces a new bpf subcommand BPF_TASK_FD_QUERY.
> Given a pid and fd, this command will return bpf related information
> to user space. Right now it only supports tracepoint/kprobe/uprobe
> perf event fd's. For such a fd, BPF_TASK_FD_QUERY will return
> . prog_id
> . tracepoint name, or
> . k[ret]probe funcname + offset or kernel addr, or
> . u[ret]probe filename + offset
> to the userspace.
> The user can use "bpftool prog" to find more information about
> bpf program itself with prog_id.
>
> Patch #1 adds function perf_get_event() in kernel/events/core.c.
> Patch #2 implements the bpf subcommand BPF_TASK_FD_QUERY.
> Patch #3 syncs tools bpf.h header and also add bpf_task_fd_query()
> in the libbpf library for samples/selftests/bpftool to use.
> Patch #4 adds ksym_get_addr() utility function.
> Patch #5 add a test in samples/bpf for querying k[ret]probes and
> u[ret]probes.
> Patch #6 add a test in tools/testing/selftests/bpf for querying
> raw_tracepoint and tracepoint.
> Patch #7 add a new subcommand "perf" to bpftool.
>
> Changelogs:
> v4 -> v5:
> . return strlen(buf) instead of strlen(buf) + 1
> in the attr.buf_len. As long as user provides
> non-empty buffer, it will be filed with empty
> string, truncated string, or full string
> based on the buffer size and the length of
> to-be-copied string.
> v3 -> v4:
> . made attr buf_len input/output. The length of
> actual buffter is written to buf_len so user space knows
> what is actually needed. If user provides a buffer
> with length >= 1 but less than required, do partial
> copy and return -ENOSPC.
> . code simplification with put_user.
> . changed query result attach_info to fd_type.
> . add tests at selftests/bpf to test zero len, null buf and
> insufficient buf.
> v2 -> v3:
> . made perf_get_event() return perf_event pointer const.
> this was to ensure that event fields are not meddled.
> . detect whether newly BPF_TASK_FD_QUERY is supported or
> not in "bpftool perf" and warn users if it is not.
> v1 -> v2:
> . changed bpf subcommand name from BPF_PERF_EVENT_QUERY
> to BPF_TASK_FD_QUERY.
> . fixed various "bpftool perf" issues and added documentation
> and auto-completion.
>
> Yonghong Song (7):
> perf/core: add perf_get_event() to return perf_event given a struct
> file
> bpf: introduce bpf subcommand BPF_TASK_FD_QUERY
> tools/bpf: sync kernel header bpf.h and add bpf_task_fd_query in
> libbpf
> tools/bpf: add ksym_get_addr() in trace_helpers
> samples/bpf: add a samples/bpf test for BPF_TASK_FD_QUERY
> tools/bpf: add two BPF_TASK_FD_QUERY tests in test_progs
> tools/bpftool: add perf subcommand
>
> include/linux/perf_event.h | 5 +
> include/linux/trace_events.h | 17 +
> include/uapi/linux/bpf.h | 26 ++
> kernel/bpf/syscall.c | 131 ++++++++
> kernel/events/core.c | 8 +
> kernel/trace/bpf_trace.c | 48 +++
> kernel/trace/trace_kprobe.c | 29 ++
> kernel/trace/trace_uprobe.c | 22 ++
> samples/bpf/Makefile | 4 +
> samples/bpf/task_fd_query_kern.c | 19 ++
> samples/bpf/task_fd_query_user.c | 382 +++++++++++++++++++++++
> tools/bpf/bpftool/Documentation/bpftool-perf.rst | 81 +++++
> tools/bpf/bpftool/Documentation/bpftool.rst | 5 +-
> tools/bpf/bpftool/bash-completion/bpftool | 9 +
> tools/bpf/bpftool/main.c | 3 +-
> tools/bpf/bpftool/main.h | 1 +
> tools/bpf/bpftool/perf.c | 246 +++++++++++++++
> tools/include/uapi/linux/bpf.h | 26 ++
> tools/lib/bpf/bpf.c | 23 ++
> tools/lib/bpf/bpf.h | 3 +
> tools/testing/selftests/bpf/test_progs.c | 158 ++++++++++
> tools/testing/selftests/bpf/trace_helpers.c | 12 +
> tools/testing/selftests/bpf/trace_helpers.h | 1 +
> 23 files changed, 1257 insertions(+), 2 deletions(-)
> create mode 100644 samples/bpf/task_fd_query_kern.c
> create mode 100644 samples/bpf/task_fd_query_user.c
> create mode 100644 tools/bpf/bpftool/Documentation/bpftool-perf.rst
> create mode 100644 tools/bpf/bpftool/perf.c
LGTM, series:
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH] PCI: allow drivers to limit the number of VFs to 0
From: Bjorn Helgaas @ 2018-05-24 23:57 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Bjorn Helgaas, linux-pci, netdev, Sathya Perla, Felix Manlunas,
alexander.duyck, john.fastabend, Jacob Keller, Donald Dutile,
oss-drivers, Christoph Hellwig
In-Reply-To: <20180402224652.4058-1-jakub.kicinski@netronome.com>
Hi Jakub,
On Mon, Apr 02, 2018 at 03:46:52PM -0700, Jakub Kicinski wrote:
> Some user space depends on enabling sriov_totalvfs number of VFs
> to not fail, e.g.:
>
> $ cat .../sriov_totalvfs > .../sriov_numvfs
>
> For devices which VF support depends on loaded FW we have the
> pci_sriov_{g,s}et_totalvfs() API. However, this API uses 0 as
> a special "unset" value, meaning drivers can't limit sriov_totalvfs
> to 0. Remove the special values completely and simply initialize
> driver_max_VFs to total_VFs. Then always use driver_max_VFs.
> Add a helper for drivers to reset the VF limit back to total.
I still can't really make sense out of the changelog.
I think part of the reason it's confusing is because there are two
things going on:
1) You want this:
pci_sriov_set_totalvfs(dev, 0);
x = pci_sriov_get_totalvfs(dev)
to return 0 instead of total_VFs. That seems to connect with
your subject line. It means "sriov_totalvfs" in sysfs could be
0, but I don't know how that is useful (I'm sure it is; just
educate me :))
2) You're adding the pci_sriov_reset_totalvfs() interface. I'm not
sure what you intend for this. Is *every* driver supposed to
call it in .remove()? Could/should this be done in the core
somehow instead of depending on every driver?
I'm also having a hard time connecting your user-space command example
with the rest of this. Maybe it will make more sense to me tomorrow
after some coffee.
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> ---
> drivers/net/ethernet/netronome/nfp/nfp_main.c | 6 +++---
> drivers/pci/iov.c | 27 +++++++++++++++++++++------
> include/linux/pci.h | 2 ++
> 3 files changed, 26 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
> index c4b1f344b4da..a76d177e40dd 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
> @@ -123,7 +123,7 @@ static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
> return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
>
> pf->limit_vfs = ~0;
> - pci_sriov_set_totalvfs(pf->pdev, 0); /* 0 is unset */
> + pci_sriov_reset_totalvfs(pf->pdev);
> /* Allow any setting for backwards compatibility if symbol not found */
> if (err == -ENOENT)
> return 0;
> @@ -537,7 +537,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
> err_net_remove:
> nfp_net_pci_remove(pf);
> err_sriov_unlimit:
> - pci_sriov_set_totalvfs(pf->pdev, 0);
> + pci_sriov_reset_totalvfs(pf->pdev);
> err_fw_unload:
> kfree(pf->rtbl);
> nfp_mip_close(pf->mip);
> @@ -570,7 +570,7 @@ static void nfp_pci_remove(struct pci_dev *pdev)
> nfp_hwmon_unregister(pf);
>
> nfp_pcie_sriov_disable(pdev);
> - pci_sriov_set_totalvfs(pf->pdev, 0);
> + pci_sriov_reset_totalvfs(pf->pdev);
>
> nfp_net_pci_remove(pf);
>
> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> index 677924ae0350..c63ea870d8be 100644
> --- a/drivers/pci/iov.c
> +++ b/drivers/pci/iov.c
> @@ -443,6 +443,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
> iov->nres = nres;
> iov->ctrl = ctrl;
> iov->total_VFs = total;
> + iov->driver_max_VFs = total;
> pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device);
> iov->pgsz = pgsz;
> iov->self = dev;
> @@ -788,12 +789,29 @@ int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
> }
> EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
>
> +/**
> + * pci_sriov_reset_totalvfs -- return the TotalVFs value to the default
> + * @dev: the PCI PF device
> + *
> + * Should be called from PF driver's remove routine with
> + * device's mutex held.
> + */
> +void pci_sriov_reset_totalvfs(struct pci_dev *dev)
> +{
> + /* Shouldn't change if VFs already enabled */
> + if (!dev->is_physfn || dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE)
> + return;
> +
> + dev->sriov->driver_max_VFs = dev->sriov->total_VFs;
> +}
> +EXPORT_SYMBOL_GPL(pci_sriov_reset_totalvfs);
> +
> /**
> * pci_sriov_get_totalvfs -- get total VFs supported on this device
> * @dev: the PCI PF device
> *
> - * For a PCIe device with SRIOV support, return the PCIe
> - * SRIOV capability value of TotalVFs or the value of driver_max_VFs
> + * For a PCIe device with SRIOV support, return the value of driver_max_VFs
> + * which can be equal to the PCIe SRIOV capability value of TotalVFs or lower
> * if the driver reduced it. Otherwise 0.
> */
> int pci_sriov_get_totalvfs(struct pci_dev *dev)
> @@ -801,9 +819,6 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev)
> if (!dev->is_physfn)
> return 0;
>
> - if (dev->sriov->driver_max_VFs)
> - return dev->sriov->driver_max_VFs;
> -
> - return dev->sriov->total_VFs;
> + return dev->sriov->driver_max_VFs;
> }
> EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 024a1beda008..95fde8850393 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1952,6 +1952,7 @@ void pci_iov_remove_virtfn(struct pci_dev *dev, int id);
> int pci_num_vf(struct pci_dev *dev);
> int pci_vfs_assigned(struct pci_dev *dev);
> int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
> +void pci_sriov_reset_totalvfs(struct pci_dev *dev);
> int pci_sriov_get_totalvfs(struct pci_dev *dev);
> resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
> void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe);
> @@ -1978,6 +1979,7 @@ static inline int pci_vfs_assigned(struct pci_dev *dev)
> { return 0; }
> static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
> { return 0; }
> +static inline void pci_sriov_reset_totalvfs(struct pci_dev *dev) { }
> static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
> { return 0; }
> static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
> --
> 2.16.2
>
^ permalink raw reply
* Re: [v8, bpf-next, 4/9] net/wireless/iwlwifi: fix iwlwifi_dev_ucode_error tracepoint
From: Steven Rostedt @ 2018-05-24 23:39 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Johannes Berg, Alexei Starovoitov, davem, daniel, torvalds,
peterz, mathieu.desnoyers, netdev, kernel-team, linux-api,
linux-wireless
In-Reply-To: <20180524232837.24jvdsdiohkpj7fs@ast-mbp>
On Thu, 24 May 2018 16:28:39 -0700
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> Ohh. I didn't realize that networking wireless doesn't fall under netdev.
> I thought wireless folks are silent because they are embarrassed
> by a function with 17 arguments.
Please lets refrain from the demeaning comments.
I agree with your argument, but not the tone.
-- Steve
^ permalink raw reply
* Re: [PATCH 00/14] Modify action API for implementing lockless actions
From: Cong Wang @ 2018-05-24 23:34 UTC (permalink / raw)
To: Vlad Buslov
Cc: Linux Kernel Network Developers, David Miller, Jamal Hadi Salim,
Jiri Pirko, Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
Alexei Starovoitov, Daniel Borkmann, Eric Dumazet, Kees Cook,
LKML, NetFilter, coreteam, kliteyn
In-Reply-To: <1526308035-12484-1-git-send-email-vladbu@mellanox.com>
On Mon, May 14, 2018 at 7:27 AM, Vlad Buslov <vladbu@mellanox.com> wrote:
> Currently, all netlink protocol handlers for updating rules, actions and
> qdiscs are protected with single global rtnl lock which removes any
> possibility for parallelism. This patch set is a first step to remove
> rtnl lock dependency from TC rules update path. It updates act API to
> use atomic operations, rcu and spinlocks for fine-grained locking. It
> also extend API with functions that are needed to update existing
> actions for parallel execution.
Can you give a summary here for what and how it is achieved?
You said this is the first step, what do you want to achieve in this
very first step? And how do you achieve it? Do you break the RTNL
lock down to, for a quick example, a per-device lock? Or perhaps you
completely remove it because of what reason?
I go through all the descriptions of your 14 patches (but not any code),
I still have no clue how you successfully avoid RTNL. Please don't
let me read into your code to understand that, there must be some
high-level justification on how it works. Without it, I don't event want
to read into the code.
Thanks.
^ permalink raw reply
* Re: [PATCH bpf-next v2 0/3] bpf: add boot parameters for sysctl knobs
From: Alexei Starovoitov @ 2018-05-24 23:34 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Eugene Syromiatnikov, netdev, linux-kernel, linux-doc, Kees Cook,
Kai-Heng Feng, Daniel Borkmann, Alexei Starovoitov,
Jonathan Corbet, Jiri Olsa
In-Reply-To: <20180524094108.066d885a@redhat.com>
On Thu, May 24, 2018 at 09:41:08AM +0200, Jesper Dangaard Brouer wrote:
> On Wed, 23 May 2018 15:02:45 -0700
> Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>
> > On Wed, May 23, 2018 at 02:18:19PM +0200, Eugene Syromiatnikov wrote:
> > > Some BPF sysctl knobs affect the loading of BPF programs, and during
> > > system boot/init stages these sysctls are not yet configured.
> > > A concrete example is systemd, that has implemented loading of BPF
> > > programs.
> > >
> > > Thus, to allow controlling these setting at early boot, this patch set
> > > adds the ability to change the default setting of these sysctl knobs
> > > as well as option to override them via a boot-time kernel parameter
> > > (in order to avoid rebuilding kernel each time a need of changing these
> > > defaults arises).
> > >
> > > The sysctl knobs in question are kernel.unprivileged_bpf_disable,
> > > net.core.bpf_jit_harden, and net.core.bpf_jit_kallsyms.
> >
> > - systemd is root. today it only uses cgroup-bpf progs which require root,
> > so disabling unpriv during boot time makes no difference to systemd.
> > what is the actual reason to present time?
> >
> > - say in the future systemd wants to use so_reuseport+bpf for faster
> > networking. With unpriv disable during boot, it will force systemd
> > to do such networking from root, which will lower its security barrier.
> > How that make sense?
> >
> > - bpf_jit_kallsyms sysctl has immediate effect on loaded programs.
> > Flipping it during the boot or right after or any time after
> > is the same thing. Why add such boot flag then?
> >
> > - jit_harden can be turned on by systemd. so turning it during the boot
> > will make systemd progs to be constant blinded.
> > Constant blinding protects kernel from unprivileged JIT spraying.
> > Are you worried that systemd will attack the kernel with JIT spraying?
>
>
> I think you are missing that, we want the ability to change these
> defaults in-order to avoid depending on /etc/sysctl.conf settings, and
> that the these sysctl.conf setting happen too late.
What does it mean 'happens too late' ?
Too late for what?
sysctl.conf has plenty of system critical knobs like
kernel.perf_event_paranoid, kernel.core_pattern, etc
The behavior of the host is drastically different after sysctl config
is applied.
> For example with jit_harden, there will be a difference between the
> loaded BPF program that got loaded at boot-time with systemd (no
> constant blinding) and when someone reloads that systemd service after
> /etc/sysctl.conf have been evaluated and setting bpf_jit_harden (now
> slower due to constant blinding). This is inconsistent behavior.
net.core.bpf_jit_harden can be flipped back and forth at run-time,
so bpf progs before and after will be either blinded or not.
I don't see any inconsistency.
In general I think bootparams should be used only for things
like kpti=on/off that cannot be set by sysctl.
^ permalink raw reply
* Re: [v8, bpf-next, 4/9] net/wireless/iwlwifi: fix iwlwifi_dev_ucode_error tracepoint
From: Alexei Starovoitov @ 2018-05-24 23:28 UTC (permalink / raw)
To: Johannes Berg
Cc: Alexei Starovoitov, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
daniel-FeC+5ew28dpmcu3hnIyYJQ,
torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
peterz-wEGCiKHe2LqWVfeAwA7xHQ, rostedt-nx8X9YLhiw1AfugRpC6u6w,
mathieu.desnoyers-vg+e7yoeK/dWk0Htik3J/w,
netdev-u79uwXL29TY76Z2rM5mHXA, kernel-team-b10kYP2dOMg,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1527073388.3759.21.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
On Wed, May 23, 2018 at 01:03:08PM +0200, Johannes Berg wrote:
> On Wed, 2018-03-28 at 12:05 -0700, Alexei Starovoitov wrote:
> > fix iwlwifi_dev_ucode_error tracepoint to pass pointer to a table
> > instead of all 17 arguments by value.
> > dvm/main.c and mvm/utils.c have 'struct iwl_error_event_table'
> > defined with very similar yet subtly different fields and offsets.
> > tracepoint is still common and using definition of 'struct iwl_error_event_table'
> > from dvm/commands.h while copying fields.
> > Long term this tracepoint probably should be split into two.
>
> It would've been nice to CC the wireless list for wireless related
> patches ...
Ohh. I didn't realize that networking wireless doesn't fall under netdev.
I thought wireless folks are silent because they are embarrassed
by a function with 17 arguments.
> > --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
> > +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
> > @@ -30,6 +30,7 @@
> > #ifndef __CHECKER__
> > #include "iwl-trans.h"
> >
> > +#include "dvm/commands.h"
>
> In particular, this breaks the whole driver abstraction.
>
> > +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
> > @@ -549,12 +549,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
> >
> > IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version);
> >
> > - trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
> > - table.data1, table.data2, table.data3,
> > - table.blink2, table.ilink1,
> > - table.ilink2, table.bcon_time, table.gp1,
> > - table.gp2, table.fw_rev_type, table.major,
> > - table.minor, table.hw_ver, table.brd_ver);
> > + trace_iwlwifi_dev_ucode_error(trans->dev, &table, table.hw_ver, table.brd_ver);
>
> This is also utterly wrong because mvm has - for better or worse - a
> different type "struct iwl_error_event_table" in this file ...
As I was trying to explain in the commit log the single struct
is used in both places, but differences in two
"struct iwl_error_event_table" are carefully matched
field and by field. For two extra fields it was not
possible and they are passed separately as you can see above.
I still believe that tracepoint output is still exactly
the same before and after the patch.
I guess you see the breakage because new fields got
added into one "struct iwl_error_event_table",
but were not added to its evil twin "struct iwl_error_event_table"
with the same name after the patch landed ?
imo wireless folks need to avoid such naming conflicts.
I suggest to isolate common fields into separate base struct and
give two children structs different names.
^ permalink raw reply
* [PATCH] ath6kl: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2018-05-24 23:13 UTC (permalink / raw)
To: Kalle Valo, David S. Miller
Cc: linux-wireless, netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 2ba8cf3..29e32cd 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3898,17 +3898,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
switch (ar->hw.cap) {
case WMI_11AN_CAP:
- ht = true;
+ ht = true; /* fall through */
case WMI_11A_CAP:
band_5gig = true;
break;
case WMI_11GN_CAP:
- ht = true;
+ ht = true; /* fall through */
case WMI_11G_CAP:
band_2gig = true;
break;
case WMI_11AGN_CAP:
- ht = true;
+ ht = true; /* fall through */
case WMI_11AG_CAP:
band_2gig = true;
band_5gig = true;
--
2.7.4
^ permalink raw reply related
* [PATCH] ath5k: mark expected switch fall-through
From: Gustavo A. R. Silva @ 2018-05-24 23:07 UTC (permalink / raw)
To: Jiri Slaby, Nick Kossifidis, Luis R. Rodriguez, Kalle Valo,
David S. Miller
Cc: linux-wireless, netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
drivers/net/wireless/ath/ath5k/pcu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index f23c851..05140d8 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -670,6 +670,7 @@ ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
break;
case NL80211_IFTYPE_ADHOC:
AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
+ /* fall through */
default:
/* On non-STA modes timer1 is used as next DMA
* beacon alert (DBA) timer and timer2 as next
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next] net: phy: convert further flags in struct phy_device to bit-field
From: Florian Fainelli @ 2018-05-24 23:03 UTC (permalink / raw)
To: Heiner Kallweit, Andrew Lunn, David Miller; +Cc: netdev@vger.kernel.org
In-Reply-To: <d148e574-2e29-a52f-7da0-13ef1ead927a@gmail.com>
On 05/24/2018 01:15 PM, Heiner Kallweit wrote:
> This patch is a follow-up to 87e5808d52b6 ("net: phy: replace bool
> members in struct phy_device with bit-fields") and converts further
> flags to bit-fields.
This looks fine, but then you would also have to clean-up all code that
does phydev->asym_pause = 1 and phydev->pause = 1 to use true/false
instead, I am not sure there is much value in doing that for these
fields considering that they are exposed to drivers so there is a risk
of possible breakage.
Thanks!
>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
> ---
> include/linux/phy.h | 17 ++++++++---------
> 1 file changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index 6cd090984..cc66f2834 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -418,21 +418,20 @@ struct phy_device {
> /* The most recently read link state */
> unsigned link:1;
>
> + /* forced speed & duplex (no autoneg)
> + * partner speed & duplex & pause (autoneg)
> + */
> + unsigned pause:1;
> + unsigned asym_pause:1;
> + int speed;
> + int duplex;
> +
> enum phy_state state;
>
> u32 dev_flags;
>
> phy_interface_t interface;
>
> - /*
> - * forced speed & duplex (no autoneg)
> - * partner speed & duplex & pause (autoneg)
> - */
> - int speed;
> - int duplex;
> - int pause;
> - int asym_pause;
> -
> /* Enabled Interrupts */
> u32 interrupts;
>
>
--
Florian
^ permalink raw reply
* [PATCH] ath10k: htt_tx: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2018-05-24 22:59 UTC (permalink / raw)
To: Kalle Valo, David S. Miller
Cc: ath10k, linux-wireless, netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Notice that in this particular case, I replaced "pass through" with
a proper "fall through" comment, which is what GCC is expecting
to find.
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
drivers/net/wireless/ath/ath10k/htt_tx.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 5d8b97a..89157c5 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1202,7 +1202,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
- /* pass through */
+ /* fall through */
case ATH10K_HW_TXRX_ETHERNET:
if (ar->hw_params.continuous_frag_desc) {
ext_desc_t = htt->frag_desc.vaddr_desc_32;
@@ -1404,7 +1404,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt,
case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
- /* pass through */
+ /* fall through */
case ATH10K_HW_TXRX_ETHERNET:
if (ar->hw_params.continuous_frag_desc) {
ext_desc_t = htt->frag_desc.vaddr_desc_64;
--
2.7.4
^ permalink raw reply related
* Re: 4.16 issue with mbim modem and ping with size > 14552 bytes
From: Daniele Palmas @ 2018-05-24 22:54 UTC (permalink / raw)
To: Greg KH; +Cc: netdev, linux-usb
In-Reply-To: <20180524155334.GA28874@kroah.com>
Hi Greg,
2018-05-24 17:53 GMT+02:00 Greg KH <gregkh@linuxfoundation.org>:
> On Thu, May 24, 2018 at 05:04:49PM +0200, Daniele Palmas wrote:
>> Hello,
>>
>> I have an issue with an USB mbim modem when trying to send with ping
>> more than 14552 bytes: it looks like to me a kernel issue, but not at
>> the cdc_mbim or cdc_ncm level, anyway not sure, so I'm reporting the
>> issue.
>>
>> My kernel is 4.16. The device is the following:
>
> Does older kernels work, or is this something that has always been
> there?
>
Not tested yet, I'm going to do.
> I ask, as my mobile provider does horrible things to large packet sizes.
> So much so that I have to set the mtu to 1280 just to get things to work
> properly when tethering my phone through to my laptop. So this might be
> a network provider issue :)
>
Yeah, I thought the same, so I tried the same scenario with Windows 10
but it is working fine.
Thanks,
Daniele
> thanks,
>
> greg k-h
^ permalink raw reply
* Re: [PATCH net] packet: in packet_snd start writing at link layer allocation
From: Willem de Bruijn @ 2018-05-24 22:13 UTC (permalink / raw)
To: Tariq Toukan
Cc: David Miller, Network Development, Eric Dumazet, Willem de Bruijn,
Maor Gottlieb
In-Reply-To: <CAF=yD-JapgdzDxtt+noXEm2Zj4dy=9N1_ALYBsz-TXA5CwtTkQ@mail.gmail.com>
On Thu, May 24, 2018 at 1:01 PM, Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
> On Thu, May 24, 2018 at 11:17 AM, Willem de Bruijn
> <willemdebruijn.kernel@gmail.com> wrote:
>> On Thu, May 24, 2018 at 11:07 AM, Tariq Toukan <tariqt@mellanox.com> wrote:
>>>
>>>
>>> On 14/05/2018 3:20 AM, David Miller wrote:
>>>>
>>>> From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
>>>> Date: Fri, 11 May 2018 13:24:25 -0400
>>>>
>>>>> From: Willem de Bruijn <willemb@google.com>
>>>>>
>>>>> Packet sockets allow construction of packets shorter than
>>>>> dev->hard_header_len to accommodate protocols with variable length
>>>>> link layer headers. These packets are padded to dev->hard_header_len,
>>>>> because some device drivers interpret that as a minimum packet size.
>>>>>
>>>>> packet_snd reserves dev->hard_header_len bytes on allocation.
>>>>> SOCK_DGRAM sockets call skb_push in dev_hard_header() to ensure that
>>>>> link layer headers are stored in the reserved range. SOCK_RAW sockets
>>>>> do the same in tpacket_snd, but not in packet_snd.
>>>>>
>>>>> Syzbot was able to send a zero byte packet to a device with massive
>>>>> 116B link layer header, causing padding to cross over into skb_shinfo.
>>>>> Fix this by writing from the start of the llheader reserved range also
>>>>> in the case of packet_snd/SOCK_RAW.
>>>>>
>>>>> Update skb_set_network_header to the new offset. This also corrects
>>>>> it for SOCK_DGRAM, where it incorrectly double counted reserve due to
>>>>> the skb_push in dev_hard_header.
>>>>>
>>>>> Fixes: 9ed988cd5915 ("packet: validate variable length ll headers")
>>>>> Reported-by: syzbot+71d74a5406d02057d559@syzkaller.appspotmail.com
>>>>> Signed-off-by: Willem de Bruijn <willemb@google.com>
>>>>
>>>>
>>>> Applied and queued up for -stable, thanks Willem.
>>>>
>>>
>>> Hi,
>>>
>>> One of our regression tests started failing. Once this patch is reverted,
>>> test passes.
>>>
>>> The tests add flow steering rules in the receiver side and in the sender
>>> side it send the packet with some RAW socket applications. Then received
>>> side gets completion with error.
>>>
>>> Our verification team compared the packets between the stable and the broken
>>> version, in the broken version we have some extra bytes at the end of the
>>> packet.
>>>
>>> It looks like some bad push to the SKB, maybe the conditional reserved
>>> addition should be more strict?
>>>
>>> Any idea?
>>
>> Thanks for reporting, sorry for the breakage.
>>
>> I think I might. This skb_push moves back the start of skb->data in the
>> same way that tpacket_snd does. But it does not reduce the length
>> passed to skb_put, so this might double count hard_header_len.
>>
>> Let me construct a test.
>
> Indeed.
>
> Still verifying, but this almost certainly has to be
>
> @@ -2911,7 +2912,7 @@ static int packet_snd(struct socket *sock,
> struct msghdr *msg, size_t len)
> if (unlikely(offset < 0))
> goto out_free;
> } else if (reserve) {
> - skb_push(skb, reserve);
> + skb_reserve(skb, -reserve);
> }
>
> to move the start of the packet without changing its length.
I sent http://patchwork.ozlabs.org/patch/920126/
Again, thanks a lot for reporting this, Tariq. I'm working on some
packet socket boundary condition tests for tools/testing/selftests/net,
so that I cannot push such a mistake again.
^ permalink raw reply
* [PATCH net] packet: fix reserve calculation
From: Willem de Bruijn @ 2018-05-24 22:10 UTC (permalink / raw)
To: netdev; +Cc: davem, Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
Commit b84bbaf7a6c8 ("packet: in packet_snd start writing at link
layer allocation") ensures that packet_snd always starts writing
the link layer header in reserved headroom allocated for this
purpose.
This is needed because packets may be shorter than hard_header_len,
in which case the space up to hard_header_len may be zeroed. But
that necessary padding is not accounted for in skb->len.
The fix, however, is buggy. It calls skb_push, which grows skb->len
when moving skb->data back. But in this case packet length should not
change.
Instead, call skb_reserve, which moves both skb->data and skb->tail
back, without changing length.
Fixes: b84bbaf7a6c8 ("packet: in packet_snd start writing at link layer allocation")
Reported-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
---
net/packet/af_packet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index e9422fe45179..acb7b86574cd 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2911,7 +2911,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
if (unlikely(offset < 0))
goto out_free;
} else if (reserve) {
- skb_push(skb, reserve);
+ skb_reserve(skb, -reserve);
}
/* Returns -EFAULT on error */
--
2.17.0.921.gf22659ad46-goog
^ permalink raw reply related
* Re: [PATCH net-next 0/8] nfp: offload LAG for tc flower egress
From: Jakub Kicinski @ 2018-05-24 22:01 UTC (permalink / raw)
To: Or Gerlitz
Cc: David Miller, Linux Netdev List, oss-drivers, Jiri Pirko,
Jay Vosburgh, Veaceslav Falico, Andy Gospodarek
In-Reply-To: <CAJ3xEMhJckJq6HDFm_QTtDP_SG1jPJ55q1b-_Vg0WoC_UqO_Wg@mail.gmail.com>
On Thu, 24 May 2018 22:26:03 +0300, Or Gerlitz wrote:
> On Thu, May 24, 2018 at 9:49 PM, Jakub Kicinski
> <jakub.kicinski@netronome.com> wrote:
> > On Thu, 24 May 2018 20:04:56 +0300, Or Gerlitz wrote:
>
> >> Does this apply also to non-uplink representors? if yes, what is the use case?
> >>
> >> We are looking on supporting uplink lag in sriov switchdev scheme - we refer to
> >> it as "vf lag" -- b/c the netdev and rdma devices seen by the VF are actually
> >> subject to HA and/or LAG - I wasn't sure if/how you limit this series
> >> to uplink reprs
> >
> > I don't think we have a limitation on the output port within the LAG.
> > But keep in mind in our devices all ports belong to the same eswitch/PF
> > so bonding uplink ports is generally sufficient, I'm not sure VF
> > bonding adds much HA. IOW AFAIK we support VF bonding because HW can do
> > it easily, not because we have a strong use case for it.
>
> To make it clear, vf lag is code name for uplink lag, I think we want
> to say that we provide the VM a lagged VF, anyway, again, the lag is
> done on the uplink reps not on the vf reps.
Ah, ack, same use case here!
> Unlike the uplink port which is physical one, the vf vport is virtual
> one, what could be the benefit to bond two vports?
I'm not sure what it could be :) We can also bond an uplink and a VF!
All outputs on the nfp are working same, so why limit ourselves if we
can do it? :)
^ permalink raw reply
* [net 2/2] net/mlx5: IPSec, Fix a race between concurrent sandbox QP commands
From: Saeed Mahameed @ 2018-05-24 21:53 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Yossi Kuperman, Adi Nissim, Saeed Mahameed
In-Reply-To: <20180524215313.7605-1-saeedm@mellanox.com>
From: Yossi Kuperman <yossiku@mellanox.com>
Sandbox QP Commands are retired in the order they are sent. Outstanding
commands are stored in a linked-list in the order they appear. Once a
response is received and the callback gets called, we pull the first
element off the pending list, assuming they correspond.
Sending a message and adding it to the pending list is not done atomically,
hence there is an opportunity for a race between concurrent requests.
Bind both send and add under a critical section.
Fixes: bebb23e6cb02 ("net/mlx5: Accel, Add IPSec acceleration interface")
Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
Signed-off-by: Adi Nissim <adin@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
index 0f5da499a223..fad8c2e3804e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
@@ -237,19 +237,17 @@ static void *mlx5_fpga_ipsec_cmd_exec(struct mlx5_core_dev *mdev,
context->buf.sg[0].data = &context->command;
spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags);
- list_add_tail(&context->list, &fdev->ipsec->pending_cmds);
+ res = mlx5_fpga_sbu_conn_sendmsg(fdev->ipsec->conn, &context->buf);
+ if (!res)
+ list_add_tail(&context->list, &fdev->ipsec->pending_cmds);
spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags);
- res = mlx5_fpga_sbu_conn_sendmsg(fdev->ipsec->conn, &context->buf);
if (res) {
- mlx5_fpga_warn(fdev, "Failure sending IPSec command: %d\n",
- res);
- spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags);
- list_del(&context->list);
- spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags);
+ mlx5_fpga_warn(fdev, "Failed to send IPSec command: %d\n", res);
kfree(context);
return ERR_PTR(res);
}
+
/* Context will be freed by wait func after completion */
return context;
}
--
2.17.0
^ permalink raw reply related
* [net 1/2] net/mlx5e: When RXFCS is set, add FCS data into checksum calculation
From: Saeed Mahameed @ 2018-05-24 21:53 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Eran Ben Elisha, Saeed Mahameed
In-Reply-To: <20180524215313.7605-1-saeedm@mellanox.com>
From: Eran Ben Elisha <eranbe@mellanox.com>
When RXFCS feature is enabled, the HW do not strip the FCS data,
however it is not present in the checksum calculated by the HW.
Fix that by manually calculating the FCS checksum and adding it to the SKB
checksum field.
Add helper function to find the FCS data for all SKB forms (linear,
one fragment or more).
Fixes: 102722fc6832 ("net/mlx5e: Add support for RXFCS feature flag")
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/en_rx.c | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 176645762e49..1ff0b0e93804 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -615,6 +615,45 @@ static inline bool is_last_ethertype_ip(struct sk_buff *skb, int *network_depth)
return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6));
}
+static __be32 mlx5e_get_fcs(struct sk_buff *skb)
+{
+ int last_frag_sz, bytes_in_prev, nr_frags;
+ u8 *fcs_p1, *fcs_p2;
+ skb_frag_t *last_frag;
+ __be32 fcs_bytes;
+
+ if (!skb_is_nonlinear(skb))
+ return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN);
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ last_frag = &skb_shinfo(skb)->frags[nr_frags - 1];
+ last_frag_sz = skb_frag_size(last_frag);
+
+ /* If all FCS data is in last frag */
+ if (last_frag_sz >= ETH_FCS_LEN)
+ return *(__be32 *)(skb_frag_address(last_frag) +
+ last_frag_sz - ETH_FCS_LEN);
+
+ fcs_p2 = (u8 *)skb_frag_address(last_frag);
+ bytes_in_prev = ETH_FCS_LEN - last_frag_sz;
+
+ /* Find where the other part of the FCS is - Linear or another frag */
+ if (nr_frags == 1) {
+ fcs_p1 = skb_tail_pointer(skb);
+ } else {
+ skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2];
+
+ fcs_p1 = skb_frag_address(prev_frag) +
+ skb_frag_size(prev_frag);
+ }
+ fcs_p1 -= bytes_in_prev;
+
+ memcpy(&fcs_bytes, fcs_p1, bytes_in_prev);
+ memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz);
+
+ return fcs_bytes;
+}
+
static inline void mlx5e_handle_csum(struct net_device *netdev,
struct mlx5_cqe64 *cqe,
struct mlx5e_rq *rq,
@@ -643,6 +682,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
skb->csum = csum_partial(skb->data + ETH_HLEN,
network_depth - ETH_HLEN,
skb->csum);
+ if (unlikely(netdev->features & NETIF_F_RXFCS))
+ skb->csum = csum_add(skb->csum,
+ (__force __wsum)mlx5e_get_fcs(skb));
rq->stats.csum_complete++;
return;
}
--
2.17.0
^ permalink raw reply related
* [pull request][net 0/2] Mellanox, mlx5 fixes 2018-05-24
From: Saeed Mahameed @ 2018-05-24 21:53 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
Hi Dave,
This series includes two mlx5 fixes.
1) add FCS data to checksum complete when required, from Eran Ben
Elisha.
2) Fix A race in IPSec sandbox QP commands, from Yossi Kuperman.
Please pull and let me know if there's any problem.
for -stable v4.15
("net/mlx5e: When RXFCS is set, add FCS data into checksum calculation")
Thanks,
Saeed.
---
git format-pullreq $NTAG "for-next" $BASE $TARGET $NTAG
The following changes since commit d546b67cda015fb92bfee93d5dc0ceadb91deaee:
net/mlx4: Fix irq-unsafe spinlock usage (2018-05-23 15:48:58 -0400)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-fixes-2018-05-24
for you to fetch changes up to 1dcbc01f73f9abc4779f71eae5e6dc61bee37229:
net/mlx5: IPSec, Fix a race between concurrent sandbox QP commands (2018-05-24 14:40:40 -0700)
----------------------------------------------------------------
mlx5-fixes-2018-05-24
----------------------------------------------------------------
Eran Ben Elisha (1):
net/mlx5e: When RXFCS is set, add FCS data into checksum calculation
Yossi Kuperman (1):
net/mlx5: IPSec, Fix a race between concurrent sandbox QP commands
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 42 ++++++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 12 +++----
2 files changed, 47 insertions(+), 7 deletions(-)
^ permalink raw reply
* Re: [PATCH net-next] net: phy: realtek: add suspend/resume callbacks for RTL8211B
From: Heiner Kallweit @ 2018-05-24 21:42 UTC (permalink / raw)
To: Andrew Lunn
Cc: David Miller, Realtek linux nic maintainers, Hau,
Florian Fainelli, netdev@vger.kernel.org, Kevin Hao
In-Reply-To: <20180524205302.GB6762@lunn.ch>
Am 24.05.2018 um 22:53 schrieb Andrew Lunn:
> On Thu, May 24, 2018 at 10:40:12PM +0200, Heiner Kallweit wrote:
>> Add RTL8211B suspend / resume callbacks.
>>
>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>> ---
>> This patch is based on my knowledge of the r8169 driver, and on some
>> guessing. Therefore I'd appreciate a confirmation from Realtek.
>>
>> The integrated PHY in some chips supported by the r8169 driver uses
>> a special sequence for power-down/-up. I have a board with a RTL8168D
>> network chip (one of the chips using the special sequence) and there
>> the PHY identifies as RTL8211B. So my guess is that this applies also
>> to external RTL8211B PHY's.
>>
>> A hint for RTL8211B requiring a special sequence is that no suspend/
>> resume callbacks are defined yet in the Realtek PHY driver.
>> Last but not least the non-standard usage of register MII_MMD_DATA
>> is in line with the description of patch 0231b1a074c6.
>> ("net: phy: realtek: Use the dummy stubs for MMD register access for rtl8211b")
>> ---
>> drivers/net/phy/realtek.c | 16 ++++++++++++++++
>> 1 file changed, 16 insertions(+)
>>
>> diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
>> index 9f48ecf9c..082fb40c6 100644
>> --- a/drivers/net/phy/realtek.c
>> +++ b/drivers/net/phy/realtek.c
>> @@ -145,6 +145,20 @@ static int rtl8211f_config_init(struct phy_device *phydev)
>> return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
>> }
>>
>> +static int rtl8211b_suspend(struct phy_device *phydev)
>> +{
>> + phy_write(phydev, MII_MMD_DATA, BIT(9));
>
> Hi Heiner
>
> Using it like this suggests it is not actually MMD_DATA, it is
> something else which just happens to use the same address as the
> optional MMD_DATA. To make this clearer, it would be good to add
> #defines for both the register address and this BIT(9). Is there any
> vendor code you know of which might give you a clue for appropriate
> names?
>
Vendor code (Realtek r8168 driver) just writes value 0x0200 to
register 0x0E. I also would have preferred to assign proper
names to register and bit. Maybe the Realtek people on cc can
provide some information.
> I guess this device also does not support EEE? Does phy_init_eee()
> correctly figure this out? Is there a chance calling phy_init_eee()
> might trigger a suspend?
>
Right, EEE isn't supported. phy_init_eee() figures this out correctly
because read_mmd callback is set to new genphy_read_mmd_unsupported.
Heiner
> Andrew
>
^ permalink raw reply
* [net-next V2 6/6] net/mlx5e: Receive buffer support for DCBX
From: Saeed Mahameed @ 2018-05-24 21:38 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <20180524213820.5910-1-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Add dcbnl's set/get buffer configuration callback that allows user to
set/get buffer size configuration and priority to buffer mapping.
By default, firmware controls receive buffer configuration and priority
of buffer mapping based on the changes in pfc settings. When set buffer
call back is triggered, the buffer configuration changes to manual mode.
The manual mode means mlx5 driver will adjust the buffer configuration
accordingly based on the changes in pfc settings.
ConnectX buffer stride is 128 Bytes. If the buffer size is not multiple
of 128, the buffer size will be rounded down to the nearest multiple of
128.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 +
.../ethernet/mellanox/mlx5/core/en_dcbnl.c | 132 +++++++++++++++++-
2 files changed, 126 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 9ab7158a7ce7..c5c7a6d687ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -278,6 +278,7 @@ struct mlx5e_dcbx {
u8 cap;
/* Buffer configuration */
+ bool manual_buffer;
u32 cable_len;
u32 xoff;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index c641d5656b2d..0a52f31fef37 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -32,8 +32,8 @@
#include <linux/device.h>
#include <linux/netdevice.h>
#include "en.h"
-
-#define MLX5E_MAX_PRIORITY 8
+#include "en/port.h"
+#include "en/port_buffer.h"
#define MLX5E_100MB (100000)
#define MLX5E_1GB (1000000)
@@ -41,6 +41,9 @@
#define MLX5E_CEE_STATE_UP 1
#define MLX5E_CEE_STATE_DOWN 0
+/* Max supported cable length is 1000 meters */
+#define MLX5E_MAX_CABLE_LENGTH 1000
+
enum {
MLX5E_VENDOR_TC_GROUP_NUM = 7,
MLX5E_LOWEST_PRIO_GROUP = 0,
@@ -338,6 +341,9 @@ static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause);
}
+ if (MLX5_BUFFER_SUPPORTED(mdev))
+ pfc->delay = priv->dcbx.cable_len;
+
return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL);
}
@@ -346,16 +352,39 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
{
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev;
+ u32 old_cable_len = priv->dcbx.cable_len;
+ struct ieee_pfc pfc_new;
+ u32 changed = 0;
u8 curr_pfc_en;
- int ret;
+ int ret = 0;
+ /* pfc_en */
mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL);
+ if (pfc->pfc_en != curr_pfc_en) {
+ ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
+ if (ret)
+ return ret;
+ mlx5_toggle_port_link(mdev);
+ changed |= MLX5E_PORT_BUFFER_PFC;
+ }
- if (pfc->pfc_en == curr_pfc_en)
- return 0;
+ if (pfc->delay &&
+ pfc->delay < MLX5E_MAX_CABLE_LENGTH &&
+ pfc->delay != priv->dcbx.cable_len) {
+ priv->dcbx.cable_len = pfc->delay;
+ changed |= MLX5E_PORT_BUFFER_CABLE_LEN;
+ }
- ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
- mlx5_toggle_port_link(mdev);
+ if (MLX5_BUFFER_SUPPORTED(mdev)) {
+ pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en;
+ if (priv->dcbx.manual_buffer)
+ ret = mlx5e_port_manual_buffer_config(priv, changed,
+ dev->mtu, &pfc_new,
+ NULL, NULL);
+
+ if (ret && (changed & MLX5E_PORT_BUFFER_CABLE_LEN))
+ priv->dcbx.cable_len = old_cable_len;
+ }
if (!ret) {
mlx5e_dbg(HW, priv,
@@ -873,6 +902,90 @@ static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
cee_cfg->pfc_enable = state;
}
+static int mlx5e_dcbnl_getbuffer(struct net_device *dev,
+ struct dcbnl_buffer *dcb_buffer)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5e_port_buffer port_buffer;
+ u8 buffer[MLX5E_MAX_PRIORITY];
+ int i, err;
+
+ if (!MLX5_BUFFER_SUPPORTED(mdev))
+ return -EOPNOTSUPP;
+
+ err = mlx5e_port_query_priority2buffer(mdev, buffer);
+ if (err)
+ return err;
+
+ for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
+ dcb_buffer->prio2buffer[i] = buffer[i];
+
+ err = mlx5e_port_query_buffer(priv, &port_buffer);
+ if (err)
+ return err;
+
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+ dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size;
+ dcb_buffer->total_size = port_buffer.port_buffer_size;
+
+ return 0;
+}
+
+static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
+ struct dcbnl_buffer *dcb_buffer)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5e_port_buffer port_buffer;
+ u8 old_prio2buffer[MLX5E_MAX_PRIORITY];
+ u32 *buffer_size = NULL;
+ u8 *prio2buffer = NULL;
+ u32 changed = 0;
+ int i, err;
+
+ if (!MLX5_BUFFER_SUPPORTED(mdev))
+ return -EOPNOTSUPP;
+
+ for (i = 0; i < DCBX_MAX_BUFFERS; i++)
+ mlx5_core_dbg(mdev, "buffer[%d]=%d\n", i, dcb_buffer->buffer_size[i]);
+
+ for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
+ mlx5_core_dbg(mdev, "priority %d buffer%d\n", i, dcb_buffer->prio2buffer[i]);
+
+ err = mlx5e_port_query_priority2buffer(mdev, old_prio2buffer);
+ if (err)
+ return err;
+
+ for (i = 0; i < MLX5E_MAX_PRIORITY; i++) {
+ if (dcb_buffer->prio2buffer[i] != old_prio2buffer[i]) {
+ changed |= MLX5E_PORT_BUFFER_PRIO2BUFFER;
+ prio2buffer = dcb_buffer->prio2buffer;
+ break;
+ }
+ }
+
+ err = mlx5e_port_query_buffer(priv, &port_buffer);
+ if (err)
+ return err;
+
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+ if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) {
+ changed |= MLX5E_PORT_BUFFER_SIZE;
+ buffer_size = dcb_buffer->buffer_size;
+ break;
+ }
+ }
+
+ if (!changed)
+ return 0;
+
+ priv->dcbx.manual_buffer = true;
+ err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL,
+ buffer_size, prio2buffer);
+ return err;
+}
+
const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.ieee_getets = mlx5e_dcbnl_ieee_getets,
.ieee_setets = mlx5e_dcbnl_ieee_setets,
@@ -884,6 +997,8 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.ieee_delapp = mlx5e_dcbnl_ieee_delapp,
.getdcbx = mlx5e_dcbnl_getdcbx,
.setdcbx = mlx5e_dcbnl_setdcbx,
+ .dcbnl_getbuffer = mlx5e_dcbnl_getbuffer,
+ .dcbnl_setbuffer = mlx5e_dcbnl_setbuffer,
/* CEE interfaces */
.setall = mlx5e_dcbnl_setall,
@@ -1091,5 +1206,8 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
+ priv->dcbx.manual_buffer = false;
+ priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
+
mlx5e_ets_init(priv);
}
--
2.17.0
^ permalink raw reply related
* [net-next V2 5/6] net/mlx5e: Receive buffer configuration
From: Saeed Mahameed @ 2018-05-24 21:38 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <20180524213820.5910-1-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Add APIs for buffer configuration based on the changes in
pfc configuration, cable len, buffer size configuration,
and priority to buffer mapping.
Note that the xoff fomula is as below
xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B]
xoff_threshold = buffer_size - xoff
xon_threshold = xoff_threshold - MTU
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 5 +
.../mellanox/mlx5/core/en/port_buffer.c | 327 ++++++++++++++++++
.../mellanox/mlx5/core/en/port_buffer.h | 75 ++++
4 files changed, 408 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 651cf3640420..9efbf193ad5a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -21,7 +21,7 @@ mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o
-mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o
+mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o
mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib_vlan.o
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index d13a86a1d702..9ab7158a7ce7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -65,6 +65,7 @@ struct page_pool;
#define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu))
#define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu))
+#define MLX5E_MAX_PRIORITY 8
#define MLX5E_MAX_DSCP 64
#define MLX5E_MAX_NUM_TC 8
@@ -275,6 +276,10 @@ struct mlx5e_dcbx {
/* The only setting that cannot be read from FW */
u8 tc_tsa[IEEE_8021QAZ_MAX_TCS];
u8 cap;
+
+ /* Buffer configuration */
+ u32 cable_len;
+ u32 xoff;
};
struct mlx5e_dcbx_dp {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
new file mode 100644
index 000000000000..c047da8752da
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "port_buffer.h"
+
+int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
+ struct mlx5e_port_buffer *port_buffer)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
+ u32 total_used = 0;
+ void *buffer;
+ void *out;
+ int err;
+ int i;
+
+ out = kzalloc(sz, GFP_KERNEL);
+ if (!out)
+ return -ENOMEM;
+
+ err = mlx5e_port_query_pbmc(mdev, out);
+ if (err)
+ goto out;
+
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+ buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]);
+ port_buffer->buffer[i].lossy =
+ MLX5_GET(bufferx_reg, buffer, lossy);
+ port_buffer->buffer[i].epsb =
+ MLX5_GET(bufferx_reg, buffer, epsb);
+ port_buffer->buffer[i].size =
+ MLX5_GET(bufferx_reg, buffer, size) << MLX5E_BUFFER_CELL_SHIFT;
+ port_buffer->buffer[i].xon =
+ MLX5_GET(bufferx_reg, buffer, xon_threshold) << MLX5E_BUFFER_CELL_SHIFT;
+ port_buffer->buffer[i].xoff =
+ MLX5_GET(bufferx_reg, buffer, xoff_threshold) << MLX5E_BUFFER_CELL_SHIFT;
+ total_used += port_buffer->buffer[i].size;
+
+ mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i,
+ port_buffer->buffer[i].size,
+ port_buffer->buffer[i].xon,
+ port_buffer->buffer[i].xoff,
+ port_buffer->buffer[i].epsb,
+ port_buffer->buffer[i].lossy);
+ }
+
+ port_buffer->port_buffer_size =
+ MLX5_GET(pbmc_reg, out, port_buffer_size) << MLX5E_BUFFER_CELL_SHIFT;
+ port_buffer->spare_buffer_size =
+ port_buffer->port_buffer_size - total_used;
+
+ mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n",
+ port_buffer->port_buffer_size,
+ port_buffer->spare_buffer_size);
+out:
+ kfree(out);
+ return err;
+}
+
+static int port_set_buffer(struct mlx5e_priv *priv,
+ struct mlx5e_port_buffer *port_buffer)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
+ void *buffer;
+ void *in;
+ int err;
+ int i;
+
+ in = kzalloc(sz, GFP_KERNEL);
+ if (!in)
+ return -ENOMEM;
+
+ err = mlx5e_port_query_pbmc(mdev, in);
+ if (err)
+ goto out;
+
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+ buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
+
+ MLX5_SET(bufferx_reg, buffer, size,
+ port_buffer->buffer[i].size >> MLX5E_BUFFER_CELL_SHIFT);
+ MLX5_SET(bufferx_reg, buffer, lossy,
+ port_buffer->buffer[i].lossy);
+ MLX5_SET(bufferx_reg, buffer, xoff_threshold,
+ port_buffer->buffer[i].xoff >> MLX5E_BUFFER_CELL_SHIFT);
+ MLX5_SET(bufferx_reg, buffer, xon_threshold,
+ port_buffer->buffer[i].xon >> MLX5E_BUFFER_CELL_SHIFT);
+ }
+
+ err = mlx5e_port_set_pbmc(mdev, in);
+out:
+ kfree(in);
+ return err;
+}
+
+/* xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B]) */
+static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
+{
+ u32 speed;
+ u32 xoff;
+ int err;
+
+ err = mlx5e_port_linkspeed(priv->mdev, &speed);
+ if (err)
+ return 0;
+
+ xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100;
+
+ mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff);
+ return xoff;
+}
+
+static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
+ u32 xoff, unsigned int mtu)
+{
+ int i;
+
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+ if (port_buffer->buffer[i].lossy) {
+ port_buffer->buffer[i].xoff = 0;
+ port_buffer->buffer[i].xon = 0;
+ continue;
+ }
+
+ if (port_buffer->buffer[i].size <
+ (xoff + mtu + (1 << MLX5E_BUFFER_CELL_SHIFT)))
+ return -ENOMEM;
+
+ port_buffer->buffer[i].xoff = port_buffer->buffer[i].size - xoff;
+ port_buffer->buffer[i].xon = port_buffer->buffer[i].xoff - mtu;
+ }
+
+ return 0;
+}
+
+/**
+ * update_buffer_lossy()
+ * mtu: device's MTU
+ * pfc_en: <input> current pfc configuration
+ * buffer: <input> current prio to buffer mapping
+ * xoff: <input> xoff value
+ * port_buffer: <output> port receive buffer configuration
+ * change: <output>
+ *
+ * Update buffer configuration based on pfc configuraiton and priority
+ * to buffer mapping.
+ * Buffer's lossy bit is changed to:
+ * lossless if there is at least one PFC enabled priority mapped to this buffer
+ * lossy if all priorities mapped to this buffer are PFC disabled
+ *
+ * Return:
+ * Return 0 if no error.
+ * Set change to true if buffer configuration is modified.
+ */
+static int update_buffer_lossy(unsigned int mtu,
+ u8 pfc_en, u8 *buffer, u32 xoff,
+ struct mlx5e_port_buffer *port_buffer,
+ bool *change)
+{
+ bool changed = false;
+ u8 lossy_count;
+ u8 prio_count;
+ u8 lossy;
+ int prio;
+ int err;
+ int i;
+
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+ prio_count = 0;
+ lossy_count = 0;
+
+ for (prio = 0; prio < MLX5E_MAX_PRIORITY; prio++) {
+ if (buffer[prio] != i)
+ continue;
+
+ prio_count++;
+ lossy_count += !(pfc_en & (1 << prio));
+ }
+
+ if (lossy_count == prio_count)
+ lossy = 1;
+ else /* lossy_count < prio_count */
+ lossy = 0;
+
+ if (lossy != port_buffer->buffer[i].lossy) {
+ port_buffer->buffer[i].lossy = lossy;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ err = update_xoff_threshold(port_buffer, xoff, mtu);
+ if (err)
+ return err;
+
+ *change = true;
+ }
+
+ return 0;
+}
+
+int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
+ u32 change, unsigned int mtu,
+ struct ieee_pfc *pfc,
+ u32 *buffer_size,
+ u8 *prio2buffer)
+{
+ struct mlx5e_port_buffer port_buffer;
+ u32 xoff = calculate_xoff(priv, mtu);
+ bool update_prio2buffer = false;
+ u8 buffer[MLX5E_MAX_PRIORITY];
+ bool update_buffer = false;
+ u32 total_used = 0;
+ u8 curr_pfc_en;
+ int err;
+ int i;
+
+ mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change);
+
+ err = mlx5e_port_query_buffer(priv, &port_buffer);
+ if (err)
+ return err;
+
+ if (change & MLX5E_PORT_BUFFER_CABLE_LEN) {
+ update_buffer = true;
+ err = update_xoff_threshold(&port_buffer, xoff, mtu);
+ if (err)
+ return err;
+ }
+
+ if (change & MLX5E_PORT_BUFFER_PFC) {
+ err = mlx5e_port_query_priority2buffer(priv->mdev, buffer);
+ if (err)
+ return err;
+
+ err = update_buffer_lossy(mtu, pfc->pfc_en, buffer, xoff,
+ &port_buffer, &update_buffer);
+ if (err)
+ return err;
+ }
+
+ if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
+ update_prio2buffer = true;
+ err = mlx5_query_port_pfc(priv->mdev, &curr_pfc_en, NULL);
+ if (err)
+ return err;
+
+ err = update_buffer_lossy(mtu, curr_pfc_en, prio2buffer, xoff,
+ &port_buffer, &update_buffer);
+ if (err)
+ return err;
+ }
+
+ if (change & MLX5E_PORT_BUFFER_SIZE) {
+ for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+ mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
+ if (!port_buffer.buffer[i].lossy && !buffer_size[i]) {
+ mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n",
+ __func__, i);
+ return -EINVAL;
+ }
+
+ port_buffer.buffer[i].size = buffer_size[i];
+ total_used += buffer_size[i];
+ }
+
+ mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used);
+
+ if (total_used > port_buffer.port_buffer_size)
+ return -EINVAL;
+
+ update_buffer = true;
+ err = update_xoff_threshold(&port_buffer, xoff, mtu);
+ if (err)
+ return err;
+ }
+
+ /* Need to update buffer configuration if xoff value is changed */
+ if (!update_buffer && xoff != priv->dcbx.xoff) {
+ update_buffer = true;
+ err = update_xoff_threshold(&port_buffer, xoff, mtu);
+ if (err)
+ return err;
+ }
+ priv->dcbx.xoff = xoff;
+
+ /* Apply the settings */
+ if (update_buffer) {
+ err = port_set_buffer(priv, &port_buffer);
+ if (err)
+ return err;
+ }
+
+ if (update_prio2buffer)
+ err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer);
+
+ return err;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
new file mode 100644
index 000000000000..34f55b81a0de
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __MLX5_EN_PORT_BUFFER_H__
+#define __MLX5_EN_PORT_BUFFER_H__
+
+#include "en.h"
+#include "port.h"
+
+#define MLX5E_MAX_BUFFER 8
+#define MLX5E_BUFFER_CELL_SHIFT 7
+#define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */
+
+#define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \
+ MLX5_CAP_PCAM_REG(mdev, pbmc) && \
+ MLX5_CAP_PCAM_REG(mdev, pptb))
+
+enum {
+ MLX5E_PORT_BUFFER_CABLE_LEN = BIT(0),
+ MLX5E_PORT_BUFFER_PFC = BIT(1),
+ MLX5E_PORT_BUFFER_PRIO2BUFFER = BIT(2),
+ MLX5E_PORT_BUFFER_SIZE = BIT(3),
+};
+
+struct mlx5e_bufferx_reg {
+ u8 lossy;
+ u8 epsb;
+ u32 size;
+ u32 xoff;
+ u32 xon;
+};
+
+struct mlx5e_port_buffer {
+ u32 port_buffer_size;
+ u32 spare_buffer_size;
+ struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER];
+};
+
+int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
+ u32 change, unsigned int mtu,
+ struct ieee_pfc *pfc,
+ u32 *buffer_size,
+ u8 *prio2buffer);
+
+int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
+ struct mlx5e_port_buffer *port_buffer);
+#endif
--
2.17.0
^ permalink raw reply related
* [net-next V2 4/6] net/mlx5: PPTB and PBMC register firmware command support
From: Saeed Mahameed @ 2018-05-24 21:38 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <20180524213820.5910-1-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Add firmware command interface to read and write PPTB and PBMC
registers.
PPTB register enables mappings priority to a specific receive buffer.
PBMC registers enables changing the receive buffer's configuration such
as buffer size, xon/xoff thresholds, buffer's lossy property and
buffer's shared property.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/en/port.c | 108 ++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/en/port.h | 5 +
include/linux/mlx5/driver.h | 2 +
include/linux/mlx5/mlx5_ifc.h | 35 ++++++
4 files changed, 150 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
index 9f04542f3661..24e3b564964f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -127,3 +127,111 @@ u32 mlx5e_port_speed2linkmodes(u32 speed)
return link_modes;
}
+
+int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
+{
+ int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
+ void *in;
+ int err;
+
+ in = kzalloc(sz, GFP_KERNEL);
+ if (!in)
+ return -ENOMEM;
+
+ MLX5_SET(pbmc_reg, in, local_port, 1);
+ err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0);
+
+ kfree(in);
+ return err;
+}
+
+int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
+{
+ int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
+ void *out;
+ int err;
+
+ out = kzalloc(sz, GFP_KERNEL);
+ if (!out)
+ return -ENOMEM;
+
+ MLX5_SET(pbmc_reg, in, local_port, 1);
+ err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1);
+
+ kfree(out);
+ return err;
+}
+
+/* buffer[i]: buffer that priority i mapped to */
+int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
+{
+ int sz = MLX5_ST_SZ_BYTES(pptb_reg);
+ u32 prio_x_buff;
+ void *out;
+ void *in;
+ int prio;
+ int err;
+
+ in = kzalloc(sz, GFP_KERNEL);
+ out = kzalloc(sz, GFP_KERNEL);
+ if (!in || !out) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ MLX5_SET(pptb_reg, in, local_port, 1);
+ err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
+ if (err)
+ goto out;
+
+ prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff);
+ for (prio = 0; prio < 8; prio++) {
+ buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF;
+ mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]);
+ }
+out:
+ kfree(in);
+ kfree(out);
+ return err;
+}
+
+int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
+{
+ int sz = MLX5_ST_SZ_BYTES(pptb_reg);
+ u32 prio_x_buff;
+ void *out;
+ void *in;
+ int prio;
+ int err;
+
+ in = kzalloc(sz, GFP_KERNEL);
+ out = kzalloc(sz, GFP_KERNEL);
+ if (!in || !out) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* First query the pptb register */
+ MLX5_SET(pptb_reg, in, local_port, 1);
+ err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
+ if (err)
+ goto out;
+
+ memcpy(in, out, sz);
+ MLX5_SET(pptb_reg, in, local_port, 1);
+
+ /* Update the pm and prio_x_buff */
+ MLX5_SET(pptb_reg, in, pm, 0xFF);
+
+ prio_x_buff = 0;
+ for (prio = 0; prio < 8; prio++)
+ prio_x_buff |= (buffer[prio] << (4 * prio));
+ MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff);
+
+ err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);
+
+out:
+ kfree(in);
+ kfree(out);
+ return err;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
index 7aae38e98a65..f8cbd8194179 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -40,4 +40,9 @@ u32 mlx5e_port_ptys2speed(u32 eth_proto_oper);
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
u32 mlx5e_port_speed2linkmodes(u32 speed);
+
+int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
+int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
+int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
+int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
#endif
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index d703774982ca..92d292454351 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -124,6 +124,8 @@ enum {
MLX5_REG_PAOS = 0x5006,
MLX5_REG_PFCC = 0x5007,
MLX5_REG_PPCNT = 0x5008,
+ MLX5_REG_PPTB = 0x500b,
+ MLX5_REG_PBMC = 0x500c,
MLX5_REG_PMAOS = 0x5012,
MLX5_REG_PUDE = 0x5009,
MLX5_REG_PMPE = 0x5010,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index f687989d336b..edbddeaacc88 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -8788,6 +8788,41 @@ struct mlx5_ifc_qpts_reg_bits {
u8 trust_state[0x3];
};
+struct mlx5_ifc_pptb_reg_bits {
+ u8 reserved_at_0[0x2];
+ u8 mm[0x2];
+ u8 reserved_at_4[0x4];
+ u8 local_port[0x8];
+ u8 reserved_at_10[0x6];
+ u8 cm[0x1];
+ u8 um[0x1];
+ u8 pm[0x8];
+
+ u8 prio_x_buff[0x20];
+
+ u8 pm_msb[0x8];
+ u8 reserved_at_48[0x10];
+ u8 ctrl_buff[0x4];
+ u8 untagged_buff[0x4];
+};
+
+struct mlx5_ifc_pbmc_reg_bits {
+ u8 reserved_at_0[0x8];
+ u8 local_port[0x8];
+ u8 reserved_at_10[0x10];
+
+ u8 xoff_timer_value[0x10];
+ u8 xoff_refresh[0x10];
+
+ u8 reserved_at_40[0x9];
+ u8 fullness_threshold[0x7];
+ u8 port_buffer_size[0x10];
+
+ struct mlx5_ifc_bufferx_reg_bits buffer[10];
+
+ u8 reserved_at_2e0[0x40];
+};
+
struct mlx5_ifc_qtct_reg_bits {
u8 reserved_at_0[0x8];
u8 port_number[0x8];
--
2.17.0
^ 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