* [PATCH net-next, 4/6] net/mlx5: Add HV VHCA infrastructure
From: Haiyang Zhang @ 2019-08-14 19:08 UTC (permalink / raw)
To: sashal@kernel.org, davem@davemloft.net, saeedm@mellanox.com,
leon@kernel.org, eranbe@mellanox.com, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: Haiyang Zhang, KY Srinivasan, Stephen Hemminger,
linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-1-git-send-email-haiyangz@microsoft.com>
From: Eran Ben Elisha <eranbe@mellanox.com>
HV VHCA is a layer which provides PF to VF communication channel based on
HyperV PCI config channel. It implements Mellanox's Inter VHCA control
communication protocol. The protocol contains control block in order to
pass messages between the PF and VF drivers, and data blocks in order to
pass actual data.
The infrastructure is agent based. Each agent will be responsible of
contiguous buffer blocks in the VHCA config space. This infrastructure will
bind agents to their blocks, and those agents can only access read/write
the buffer blocks assigned to them. Each agent will provide three
callbacks (control, invalidate, cleanup). Control will be invoked when
block-0 is invalidated with a command that concerns this agent. Invalidate
callback will be invoked if one of the blocks assigned to this agent was
invalidated. Cleanup will be invoked before the agent is being freed in
order to clean all of its open resources or deferred works.
Block-0 serves as the control block. All execution commands from the PF
will be written by the PF over this block. VF will ack on those by
writing on block-0 as well. Its format is described by struct
mlx5_hv_vhca_control_block layout.
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
.../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 247 +++++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 102 +++++++++
drivers/net/ethernet/mellanox/mlx5/core/main.c | 7 +
include/linux/mlx5/driver.h | 2 +
5 files changed, 359 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index a8950b1..e0a1056 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -45,7 +45,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offlo
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o
-mlx5_core-$(CONFIG_PCI_HYPERV_MINI) += lib/hv.o
+mlx5_core-$(CONFIG_PCI_HYPERV_MINI)+= lib/hv.o lib/hv_vhca.o
#
# Ipoib netdev
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
new file mode 100644
index 0000000..b2eebdf
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+// Copyright (c) 2018 Mellanox Technologies
+
+#include <linux/hyperv.h>
+#include "mlx5_core.h"
+#include "lib/hv.h"
+#include "lib/hv_vhca.h"
+
+struct mlx5_hv_vhca {
+ struct mlx5_core_dev *dev;
+ struct workqueue_struct *work_queue;
+ struct mlx5_hv_vhca_agent *agents[MLX5_HV_VHCA_AGENT_MAX];
+ struct mutex agents_lock; /* Protect agents array */
+};
+
+struct mlx5_hv_vhca_work {
+ struct work_struct invalidate_work;
+ struct mlx5_hv_vhca *hv_vhca;
+ u64 block_mask;
+};
+
+struct mlx5_hv_vhca_data_block {
+ u16 sequence;
+ u16 offset;
+ u8 reserved[4];
+ u64 data[15];
+};
+
+struct mlx5_hv_vhca_agent {
+ enum mlx5_hv_vhca_agent_type type;
+ struct mlx5_hv_vhca *hv_vhca;
+ void *priv;
+ int seq;
+ void (*control)(struct mlx5_hv_vhca_agent *agent,
+ struct mlx5_hv_vhca_control_block *block);
+ void (*invalidate)(struct mlx5_hv_vhca_agent *agent,
+ u64 block_mask);
+ void (*cleanup)(struct mlx5_hv_vhca_agent *agent);
+};
+
+struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev)
+{
+ struct mlx5_hv_vhca *hv_vhca = NULL;
+
+ hv_vhca = kzalloc(sizeof(*hv_vhca), GFP_KERNEL);
+ if (!hv_vhca)
+ return ERR_PTR(-ENOMEM);
+
+ hv_vhca->work_queue = create_singlethread_workqueue("mlx5_hv_vhca");
+ if (!hv_vhca->work_queue) {
+ kfree(hv_vhca);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ hv_vhca->dev = dev;
+ mutex_init(&hv_vhca->agents_lock);
+
+ return hv_vhca;
+}
+
+void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca)
+{
+ if (IS_ERR_OR_NULL(hv_vhca))
+ return;
+
+ flush_workqueue(hv_vhca->work_queue);
+ destroy_workqueue(hv_vhca->work_queue);
+ kfree(hv_vhca);
+}
+
+static void mlx5_hv_vhca_invalidate_work(struct work_struct *work)
+{
+ struct mlx5_hv_vhca_work *hwork;
+ struct mlx5_hv_vhca *hv_vhca;
+ int i;
+
+ hwork = container_of(work, struct mlx5_hv_vhca_work, invalidate_work);
+ hv_vhca = hwork->hv_vhca;
+
+ mutex_lock(&hv_vhca->agents_lock);
+ for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) {
+ struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i];
+
+ if (!agent || !agent->invalidate)
+ continue;
+
+ if (!(BIT(agent->type) & hwork->block_mask))
+ continue;
+
+ agent->invalidate(agent, hwork->block_mask);
+ }
+ mutex_unlock(&hv_vhca->agents_lock);
+
+ kfree(hwork);
+}
+
+void mlx5_hv_vhca_invalidate(void *context, u64 block_mask)
+{
+ struct mlx5_hv_vhca *hv_vhca = (struct mlx5_hv_vhca *)context;
+ struct mlx5_hv_vhca_work *work;
+
+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return;
+
+ INIT_WORK(&work->invalidate_work, mlx5_hv_vhca_invalidate_work);
+ work->hv_vhca = hv_vhca;
+ work->block_mask = block_mask;
+
+ queue_work(hv_vhca->work_queue, &work->invalidate_work);
+}
+
+int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca)
+{
+ if (IS_ERR_OR_NULL(hv_vhca))
+ return IS_ERR_OR_NULL(hv_vhca);
+
+ return mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca,
+ mlx5_hv_vhca_invalidate);
+}
+
+void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
+{
+ int i;
+
+ if (IS_ERR_OR_NULL(hv_vhca))
+ return;
+
+ mutex_lock(&hv_vhca->agents_lock);
+ for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++)
+ WARN_ON(hv_vhca->agents[i]);
+
+ mutex_unlock(&hv_vhca->agents_lock);
+
+ mlx5_hv_unregister_invalidate(hv_vhca->dev);
+}
+
+struct mlx5_hv_vhca_agent *
+mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
+ enum mlx5_hv_vhca_agent_type type,
+ void (*control)(struct mlx5_hv_vhca_agent*,
+ struct mlx5_hv_vhca_control_block *block),
+ void (*invalidate)(struct mlx5_hv_vhca_agent*,
+ u64 block_mask),
+ void (*cleaup)(struct mlx5_hv_vhca_agent *agent),
+ void *priv)
+{
+ struct mlx5_hv_vhca_agent *agent;
+
+ if (IS_ERR_OR_NULL(hv_vhca))
+ return ERR_PTR(-ENOMEM);
+
+ if (hv_vhca->agents[type])
+ return ERR_PTR(-EINVAL);
+
+ agent = kzalloc(sizeof(*agent), GFP_KERNEL);
+ if (!agent)
+ return ERR_PTR(-ENOMEM);
+
+ agent->type = type;
+ agent->hv_vhca = hv_vhca;
+ agent->priv = priv;
+ agent->control = control;
+ agent->invalidate = invalidate;
+ agent->cleanup = cleaup;
+
+ mutex_lock(&hv_vhca->agents_lock);
+ hv_vhca->agents[type] = agent;
+ mutex_unlock(&hv_vhca->agents_lock);
+
+ return agent;
+}
+
+void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent)
+{
+ struct mlx5_hv_vhca *hv_vhca = agent->hv_vhca;
+
+ mutex_lock(&hv_vhca->agents_lock);
+
+ if (WARN_ON(agent != hv_vhca->agents[agent->type])) {
+ mutex_unlock(&hv_vhca->agents_lock);
+ return;
+ }
+
+ hv_vhca->agents[agent->type] = NULL;
+ mutex_unlock(&hv_vhca->agents_lock);
+
+ if (agent->cleanup)
+ agent->cleanup(agent);
+
+ kfree(agent);
+}
+
+static int mlx5_hv_vhca_data_block_prepare(struct mlx5_hv_vhca_agent *agent,
+ struct mlx5_hv_vhca_data_block *data_block,
+ void *src, int len, int *offset)
+{
+ int bytes = min_t(int, (int)sizeof(data_block->data), len);
+
+ data_block->sequence = agent->seq;
+ data_block->offset = (*offset)++;
+ memcpy(data_block->data, src, bytes);
+
+ return bytes;
+}
+
+static void mlx5_hv_vhca_agent_seq_update(struct mlx5_hv_vhca_agent *agent)
+{
+ agent->seq++;
+}
+
+int mlx5_hv_vhca_agent_write(struct mlx5_hv_vhca_agent *agent,
+ void *buf, int len)
+{
+ int offset = agent->type * HV_CONFIG_BLOCK_SIZE_MAX;
+ int block_offset = 0;
+ int total = 0;
+ int err;
+
+ while (len) {
+ struct mlx5_hv_vhca_data_block data_block = {0};
+ int bytes;
+
+ bytes = mlx5_hv_vhca_data_block_prepare(agent, &data_block,
+ buf + total,
+ len, &block_offset);
+ if (!bytes)
+ return -ENOMEM;
+
+ err = mlx5_hv_write_config(agent->hv_vhca->dev, &data_block,
+ sizeof(data_block), offset);
+ if (err)
+ return err;
+
+ total += bytes;
+ len -= bytes;
+ }
+
+ mlx5_hv_vhca_agent_seq_update(agent);
+
+ return 0;
+}
+
+void *mlx5_hv_vhca_agent_priv(struct mlx5_hv_vhca_agent *agent)
+{
+ return agent->priv;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
new file mode 100644
index 0000000..fa7ee85
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __LIB_HV_VHCA_H__
+#define __LIB_HV_VHCA_H__
+
+#include "en.h"
+#include "lib/hv.h"
+
+struct mlx5_hv_vhca_agent;
+struct mlx5_hv_vhca;
+struct mlx5_hv_vhca_control_block;
+
+enum mlx5_hv_vhca_agent_type {
+ MLX5_HV_VHCA_AGENT_MAX = 32,
+};
+
+#if IS_ENABLED(CONFIG_PCI_HYPERV_MINI)
+
+struct mlx5_hv_vhca_control_block {
+ u32 capabilities;
+ u32 control;
+ u16 command;
+ u16 command_ack;
+ u16 version;
+ u16 rings;
+ u32 reserved1[28];
+};
+
+struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev);
+void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca);
+int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca);
+void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca);
+void mlx5_hv_vhca_invalidate(void *context, u64 block_mask);
+
+struct mlx5_hv_vhca_agent *
+mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
+ enum mlx5_hv_vhca_agent_type type,
+ void (*control)(struct mlx5_hv_vhca_agent*,
+ struct mlx5_hv_vhca_control_block *block),
+ void (*invalidate)(struct mlx5_hv_vhca_agent*,
+ u64 block_mask),
+ void (*cleanup)(struct mlx5_hv_vhca_agent *agent),
+ void *context);
+
+void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent);
+int mlx5_hv_vhca_agent_write(struct mlx5_hv_vhca_agent *agent,
+ void *buf, int len);
+void *mlx5_hv_vhca_agent_priv(struct mlx5_hv_vhca_agent *agent);
+
+#else
+
+static inline struct mlx5_hv_vhca *
+mlx5_hv_vhca_create(struct mlx5_core_dev *dev)
+{
+ return NULL;
+}
+
+static inline void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca)
+{
+}
+
+static inline int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca)
+{
+ return 0;
+}
+
+static inline void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
+{
+}
+
+static inline void mlx5_hv_vhca_invalidate(void *context,
+ u64 block_mask)
+{
+}
+
+static inline struct mlx5_hv_vhca_agent *
+mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
+ enum mlx5_hv_vhca_agent_type type,
+ void (*control)(struct mlx5_hv_vhca_agent*,
+ struct mlx5_hv_vhca_control_block *block),
+ void (*invalidate)(struct mlx5_hv_vhca_agent*,
+ u64 block_mask),
+ void (*cleanup)(struct mlx5_hv_vhca_agent *agent),
+ void *context)
+{
+ return NULL;
+}
+
+static inline void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent)
+{
+}
+
+static inline int
+mlx5_hv_vhca_write_agent(struct mlx5_hv_vhca_agent *agent,
+ void *buf, int len)
+{
+ return 0;
+}
+#endif
+
+#endif /* __LIB_HV_VHCA_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 4cc90eb..50ee38b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -69,6 +69,7 @@
#include "lib/pci_vsc.h"
#include "diag/fw_tracer.h"
#include "ecpf.h"
+#include "lib/hv_vhca.h"
MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
@@ -872,6 +873,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
}
dev->tracer = mlx5_fw_tracer_create(dev);
+ dev->hv_vhca = mlx5_hv_vhca_create(dev);
return 0;
@@ -902,6 +904,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
{
+ mlx5_hv_vhca_destroy(dev->hv_vhca);
mlx5_fw_tracer_destroy(dev->tracer);
mlx5_fpga_cleanup(dev);
mlx5_eswitch_cleanup(dev->priv.eswitch);
@@ -1068,6 +1071,8 @@ static int mlx5_load(struct mlx5_core_dev *dev)
goto err_fw_tracer;
}
+ mlx5_hv_vhca_init(dev->hv_vhca);
+
err = mlx5_fpga_device_start(dev);
if (err) {
mlx5_core_err(dev, "fpga device start failed %d\n", err);
@@ -1123,6 +1128,7 @@ static int mlx5_load(struct mlx5_core_dev *dev)
err_ipsec_start:
mlx5_fpga_device_stop(dev);
err_fpga_start:
+ mlx5_hv_vhca_cleanup(dev->hv_vhca);
mlx5_fw_tracer_cleanup(dev->tracer);
err_fw_tracer:
mlx5_eq_table_destroy(dev);
@@ -1143,6 +1149,7 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
mlx5_accel_ipsec_cleanup(dev);
mlx5_accel_tls_cleanup(dev);
mlx5_fpga_device_stop(dev);
+ mlx5_hv_vhca_cleanup(dev->hv_vhca);
mlx5_fw_tracer_cleanup(dev->tracer);
mlx5_eq_table_destroy(dev);
mlx5_irq_table_destroy(dev);
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 2b84ee9..97bb98c 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -646,6 +646,7 @@ struct mlx5_clock {
struct mlx5_fw_tracer;
struct mlx5_vxlan;
struct mlx5_geneve;
+struct mlx5_hv_vhca;
struct mlx5_core_dev {
struct device *device;
@@ -693,6 +694,7 @@ struct mlx5_core_dev {
struct mlx5_ib_clock_info *clock_info;
struct mlx5_fw_tracer *tracer;
u32 vsc_addr;
+ struct mlx5_hv_vhca *hv_vhca;
};
struct mlx5_db {
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next, 5/6] net/mlx5: Add HV VHCA control agent
From: Haiyang Zhang @ 2019-08-14 19:09 UTC (permalink / raw)
To: sashal@kernel.org, davem@davemloft.net, saeedm@mellanox.com,
leon@kernel.org, eranbe@mellanox.com, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: Haiyang Zhang, KY Srinivasan, Stephen Hemminger,
linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-1-git-send-email-haiyangz@microsoft.com>
From: Eran Ben Elisha <eranbe@mellanox.com>
Control agent is responsible over of the control block (ID 0). It should
update the PF via this block about every capability change. In addition,
upon block 0 invalidate, it should activate all other supported agents
with data requests from the PF.
Upon agent create/destroy, the invalidate callback of the control agent
is being called in order to update the PF driver about this change.
The control agent is an integral part of HV VHCA and will be created
and destroy as part of the HV VHCA init/cleanup flow.
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 122 ++++++++++++++++++++-
.../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 1 +
2 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
index b2eebdf..3c7fffa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
@@ -110,22 +110,131 @@ void mlx5_hv_vhca_invalidate(void *context, u64 block_mask)
queue_work(hv_vhca->work_queue, &work->invalidate_work);
}
+#define AGENT_MASK(type) (type ? BIT(type - 1) : 0 /* control */)
+
+static void mlx5_hv_vhca_agents_control(struct mlx5_hv_vhca *hv_vhca,
+ struct mlx5_hv_vhca_control_block *block)
+{
+ int i;
+
+ for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) {
+ struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i];
+
+ if (!agent || !agent->control)
+ continue;
+
+ if (!(AGENT_MASK(agent->type) & block->control))
+ continue;
+
+ agent->control(agent, block);
+ }
+}
+
+static void mlx5_hv_vhca_capabilities(struct mlx5_hv_vhca *hv_vhca,
+ u32 *capabilities)
+{
+ int i;
+
+ for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) {
+ struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i];
+
+ if (agent)
+ *capabilities |= AGENT_MASK(agent->type);
+ }
+}
+
+static void
+mlx5_hv_vhca_control_agent_invalidate(struct mlx5_hv_vhca_agent *agent,
+ u64 block_mask)
+{
+ struct mlx5_hv_vhca *hv_vhca = agent->hv_vhca;
+ struct mlx5_core_dev *dev = hv_vhca->dev;
+ struct mlx5_hv_vhca_control_block *block;
+ u32 capabilities = 0;
+ int err;
+
+ block = kzalloc(sizeof(*block), GFP_KERNEL);
+ if (!block)
+ return;
+
+ err = mlx5_hv_read_config(dev, block, sizeof(*block), 0);
+ if (err)
+ goto free_block;
+
+ mlx5_hv_vhca_capabilities(hv_vhca, &capabilities);
+
+ /* In case no capabilities, send empty block in return */
+ if (!capabilities) {
+ memset(block, 0, sizeof(*block));
+ goto write;
+ }
+
+ if (block->capabilities != capabilities)
+ block->capabilities = capabilities;
+
+ if (block->control & ~capabilities)
+ goto free_block;
+
+ mlx5_hv_vhca_agents_control(hv_vhca, block);
+ block->command_ack = block->command;
+
+write:
+ mlx5_hv_write_config(dev, block, sizeof(*block), 0);
+
+free_block:
+ kfree(block);
+}
+
+static struct mlx5_hv_vhca_agent *
+mlx5_hv_vhca_control_agent_create(struct mlx5_hv_vhca *hv_vhca)
+{
+ return mlx5_hv_vhca_agent_create(hv_vhca, MLX5_HV_VHCA_AGENT_CONTROL,
+ NULL,
+ mlx5_hv_vhca_control_agent_invalidate,
+ NULL, NULL);
+}
+
+static void mlx5_hv_vhca_control_agent_destroy(struct mlx5_hv_vhca_agent *agent)
+{
+ mlx5_hv_vhca_agent_destroy(agent);
+}
+
int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca)
{
+ struct mlx5_hv_vhca_agent *agent;
+ int err;
+
if (IS_ERR_OR_NULL(hv_vhca))
return IS_ERR_OR_NULL(hv_vhca);
- return mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca,
- mlx5_hv_vhca_invalidate);
+ err = mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca,
+ mlx5_hv_vhca_invalidate);
+ if (err)
+ return err;
+
+ agent = mlx5_hv_vhca_control_agent_create(hv_vhca);
+ if (IS_ERR_OR_NULL(agent)) {
+ mlx5_hv_unregister_invalidate(hv_vhca->dev);
+ return IS_ERR_OR_NULL(agent);
+ }
+
+ hv_vhca->agents[MLX5_HV_VHCA_AGENT_CONTROL] = agent;
+
+ return 0;
}
void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
{
+ struct mlx5_hv_vhca_agent *agent;
int i;
if (IS_ERR_OR_NULL(hv_vhca))
return;
+ agent = hv_vhca->agents[MLX5_HV_VHCA_AGENT_CONTROL];
+ if (!IS_ERR_OR_NULL(agent))
+ mlx5_hv_vhca_control_agent_destroy(agent);
+
mutex_lock(&hv_vhca->agents_lock);
for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++)
WARN_ON(hv_vhca->agents[i]);
@@ -135,6 +244,11 @@ void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
mlx5_hv_unregister_invalidate(hv_vhca->dev);
}
+static void mlx5_hv_vhca_agents_update(struct mlx5_hv_vhca *hv_vhca)
+{
+ mlx5_hv_vhca_invalidate(hv_vhca, BIT(MLX5_HV_VHCA_AGENT_CONTROL));
+}
+
struct mlx5_hv_vhca_agent *
mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
enum mlx5_hv_vhca_agent_type type,
@@ -168,6 +282,8 @@ struct mlx5_hv_vhca_agent *
hv_vhca->agents[type] = agent;
mutex_unlock(&hv_vhca->agents_lock);
+ mlx5_hv_vhca_agents_update(hv_vhca);
+
return agent;
}
@@ -189,6 +305,8 @@ void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent)
agent->cleanup(agent);
kfree(agent);
+
+ mlx5_hv_vhca_agents_update(hv_vhca);
}
static int mlx5_hv_vhca_data_block_prepare(struct mlx5_hv_vhca_agent *agent,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
index fa7ee85..6f4bfb1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
@@ -12,6 +12,7 @@
struct mlx5_hv_vhca_control_block;
enum mlx5_hv_vhca_agent_type {
+ MLX5_HV_VHCA_AGENT_CONTROL = 0,
MLX5_HV_VHCA_AGENT_MAX = 32,
};
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next, 3/6] net/mlx5: Add wrappers for HyperV PCIe operations
From: Haiyang Zhang @ 2019-08-14 19:08 UTC (permalink / raw)
To: sashal@kernel.org, davem@davemloft.net, saeedm@mellanox.com,
leon@kernel.org, eranbe@mellanox.com, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: Haiyang Zhang, KY Srinivasan, Stephen Hemminger,
linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-1-git-send-email-haiyangz@microsoft.com>
From: Eran Ben Elisha <eranbe@mellanox.com>
Add wrapper functions for HyperV PCIe read / write /
block_invalidate_register operations. This will be used as an
infrastructure in the downstream patch for software communication.
This will be enabled by default if CONFIG_PCI_HYPERV_MINI is set.
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/Makefile | 1 +
drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c | 64 ++++++++++++++++++++++++
drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h | 22 ++++++++
3 files changed, 87 insertions(+)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 8b7edaa..a8950b1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -45,6 +45,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offlo
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o
+mlx5_core-$(CONFIG_PCI_HYPERV_MINI) += lib/hv.o
#
# Ipoib netdev
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c
new file mode 100644
index 0000000..cf08d02
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+// Copyright (c) 2018 Mellanox Technologies
+
+#include <linux/hyperv.h>
+#include "mlx5_core.h"
+#include "lib/hv.h"
+
+static int mlx5_hv_config_common(struct mlx5_core_dev *dev, void *buf, int len,
+ int offset, bool read)
+{
+ int rc = -EOPNOTSUPP;
+ int bytes_returned;
+ int block_id;
+
+ if (offset % HV_CONFIG_BLOCK_SIZE_MAX || len % HV_CONFIG_BLOCK_SIZE_MAX)
+ return -EINVAL;
+
+ block_id = offset / HV_CONFIG_BLOCK_SIZE_MAX;
+
+ rc = read ?
+ hyperv_read_cfg_blk(dev->pdev, buf,
+ HV_CONFIG_BLOCK_SIZE_MAX, block_id,
+ &bytes_returned) :
+ hyperv_write_cfg_blk(dev->pdev, buf,
+ HV_CONFIG_BLOCK_SIZE_MAX, block_id);
+
+ /* Make sure len bytes were read successfully */
+ if (read)
+ rc |= !(len == bytes_returned);
+
+ if (rc) {
+ mlx5_core_err(dev, "Failed to %s hv config, err = %d, len = %d, offset = %d\n",
+ read ? "read" : "write", rc, len,
+ offset);
+ return rc;
+ }
+
+ return 0;
+}
+
+int mlx5_hv_read_config(struct mlx5_core_dev *dev, void *buf, int len,
+ int offset)
+{
+ return mlx5_hv_config_common(dev, buf, len, offset, true);
+}
+
+int mlx5_hv_write_config(struct mlx5_core_dev *dev, void *buf, int len,
+ int offset)
+{
+ return mlx5_hv_config_common(dev, buf, len, offset, false);
+}
+
+int mlx5_hv_register_invalidate(struct mlx5_core_dev *dev, void *context,
+ void (*block_invalidate)(void *context,
+ u64 block_mask))
+{
+ return hyperv_reg_block_invalidate(dev->pdev, context,
+ block_invalidate);
+}
+
+void mlx5_hv_unregister_invalidate(struct mlx5_core_dev *dev)
+{
+ hyperv_reg_block_invalidate(dev->pdev, NULL, NULL);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h
new file mode 100644
index 0000000..7f69771
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2019 Mellanox Technologies. */
+
+#ifndef __LIB_HV_H__
+#define __LIB_HV_H__
+
+#if IS_ENABLED(CONFIG_PCI_HYPERV_MINI)
+
+#include <linux/hyperv.h>
+#include <linux/mlx5/driver.h>
+
+int mlx5_hv_read_config(struct mlx5_core_dev *dev, void *buf, int len,
+ int offset);
+int mlx5_hv_write_config(struct mlx5_core_dev *dev, void *buf, int len,
+ int offset);
+int mlx5_hv_register_invalidate(struct mlx5_core_dev *dev, void *context,
+ void (*block_invalidate)(void *context,
+ u64 block_mask));
+void mlx5_hv_unregister_invalidate(struct mlx5_core_dev *dev);
+#endif
+
+#endif /* __LIB_HV_H__ */
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next, 2/6] PCI: hv: Add a Hyper-V PCI mini driver for software backchannel interface
From: Haiyang Zhang @ 2019-08-14 19:08 UTC (permalink / raw)
To: sashal@kernel.org, davem@davemloft.net, saeedm@mellanox.com,
leon@kernel.org, eranbe@mellanox.com, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: Haiyang Zhang, KY Srinivasan, Stephen Hemminger,
linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-1-git-send-email-haiyangz@microsoft.com>
This mini driver is a helper driver allows other drivers to
have a common interface with the Hyper-V PCI frontend driver.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
MAINTAINERS | 1 +
drivers/pci/Kconfig | 1 +
drivers/pci/controller/Kconfig | 7 ++++
drivers/pci/controller/Makefile | 1 +
drivers/pci/controller/pci-hyperv-mini.c | 70 ++++++++++++++++++++++++++++++++
drivers/pci/controller/pci-hyperv.c | 12 ++++--
include/linux/hyperv.h | 30 ++++++++++----
7 files changed, 111 insertions(+), 11 deletions(-)
create mode 100644 drivers/pci/controller/pci-hyperv-mini.c
diff --git a/MAINTAINERS b/MAINTAINERS
index e352550..c4962b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7453,6 +7453,7 @@ F: drivers/hid/hid-hyperv.c
F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
F: drivers/pci/controller/pci-hyperv.c
+F: drivers/pci/controller/pci-hyperv-mini.c
F: drivers/net/hyperv/
F: drivers/scsi/storvsc_drv.c
F: drivers/uio/uio_hv_generic.c
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 2ab9240..bb852f5 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -182,6 +182,7 @@ config PCI_LABEL
config PCI_HYPERV
tristate "Hyper-V PCI Frontend"
depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+ select PCI_HYPERV_MINI
help
The PCI device frontend driver allows the kernel to import arbitrary
PCI devices from a PCI backend to support PCI driver domains.
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index fe9f9f1..8e31cba 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -281,5 +281,12 @@ config VMD
To compile this driver as a module, choose M here: the
module will be called vmd.
+config PCI_HYPERV_MINI
+ tristate "Hyper-V PCI Mini"
+ depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+ help
+ The Hyper-V PCI Mini is a helper driver allows other drivers to
+ have a common interface with the Hyper-V PCI frontend driver.
+
source "drivers/pci/controller/dwc/Kconfig"
endmenu
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index d56a507..77e0132 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
+obj-$(CONFIG_PCI_HYPERV_MINI) += pci-hyperv-mini.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
diff --git a/drivers/pci/controller/pci-hyperv-mini.c b/drivers/pci/controller/pci-hyperv-mini.c
new file mode 100644
index 0000000..9b6cd1c
--- /dev/null
+++ b/drivers/pci/controller/pci-hyperv-mini.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Microsoft Corporation.
+ *
+ * Author:
+ * Haiyang Zhang <haiyangz@microsoft.com>
+ *
+ * This mini driver is a helper driver allows other drivers to
+ * have a common interface with the Hyper-V PCI frontend driver.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/hyperv.h>
+
+struct hyperv_pci_block_ops hvpci_block_ops;
+EXPORT_SYMBOL(hvpci_block_ops);
+
+int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len,
+ unsigned int block_id, unsigned int *bytes_returned)
+{
+ if (!hvpci_block_ops.read_block)
+ return -EOPNOTSUPP;
+
+ return hvpci_block_ops.read_block(dev, buf, buf_len, block_id,
+ bytes_returned);
+}
+EXPORT_SYMBOL(hyperv_read_cfg_blk);
+
+int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len,
+ unsigned int block_id)
+{
+ if (!hvpci_block_ops.write_block)
+ return -EOPNOTSUPP;
+
+ return hvpci_block_ops.write_block(dev, buf, len, block_id);
+}
+EXPORT_SYMBOL(hyperv_write_cfg_blk);
+
+int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context,
+ void (*block_invalidate)(void *context,
+ u64 block_mask))
+{
+ if (!hvpci_block_ops.reg_blk_invalidate)
+ return -EOPNOTSUPP;
+
+ return hvpci_block_ops.reg_blk_invalidate(dev, context,
+ block_invalidate);
+}
+EXPORT_SYMBOL(hyperv_reg_block_invalidate);
+
+static void __exit exit_hv_pci_mini(void)
+{
+ pr_info("unloaded\n");
+}
+
+static int __init init_hv_pci_mini(void)
+{
+ pr_info("loaded\n");
+
+ return 0;
+}
+
+module_init(init_hv_pci_mini);
+module_exit(exit_hv_pci_mini);
+
+MODULE_DESCRIPTION("Hyper-V PCI Mini");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 57adeca..9c93ac2 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -983,7 +983,6 @@ int hv_read_config_block(struct pci_dev *pdev, void *buf, unsigned int len,
*bytes_returned = comp_pkt.bytes_returned;
return 0;
}
-EXPORT_SYMBOL(hv_read_config_block);
/**
* hv_pci_write_config_compl() - Invoked when a response packet for a write
@@ -1070,7 +1069,6 @@ int hv_write_config_block(struct pci_dev *pdev, void *buf, unsigned int len,
return 0;
}
-EXPORT_SYMBOL(hv_write_config_block);
/**
* hv_register_block_invalidate() - Invoked when a config block invalidation
@@ -1101,7 +1099,6 @@ int hv_register_block_invalidate(struct pci_dev *pdev, void *context,
return 0;
}
-EXPORT_SYMBOL(hv_register_block_invalidate);
/* Interrupt management hooks */
static void hv_int_desc_free(struct hv_pci_dev *hpdev,
@@ -3045,10 +3042,19 @@ static int hv_pci_remove(struct hv_device *hdev)
static void __exit exit_hv_pci_drv(void)
{
vmbus_driver_unregister(&hv_pci_drv);
+
+ hvpci_block_ops.read_block = NULL;
+ hvpci_block_ops.write_block = NULL;
+ hvpci_block_ops.reg_blk_invalidate = NULL;
}
static int __init init_hv_pci_drv(void)
{
+ /* Initialize PCI block r/w interface */
+ hvpci_block_ops.read_block = hv_read_config_block;
+ hvpci_block_ops.write_block = hv_write_config_block;
+ hvpci_block_ops.reg_blk_invalidate = hv_register_block_invalidate;
+
return vmbus_driver_register(&hv_pci_drv);
}
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 9d37f8c..2afe6fd 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1579,18 +1579,32 @@ struct vmpacket_descriptor *
pkt = hv_pkt_iter_next(channel, pkt))
/*
- * Functions for passing data between SR-IOV PF and VF drivers. The VF driver
+ * Interface for passing data between SR-IOV PF and VF drivers. The VF driver
* sends requests to read and write blocks. Each block must be 128 bytes or
* smaller. Optionally, the VF driver can register a callback function which
* will be invoked when the host says that one or more of the first 64 block
* IDs is "invalid" which means that the VF driver should reread them.
*/
#define HV_CONFIG_BLOCK_SIZE_MAX 128
-int hv_read_config_block(struct pci_dev *dev, void *buf, unsigned int buf_len,
- unsigned int block_id, unsigned int *bytes_returned);
-int hv_write_config_block(struct pci_dev *dev, void *buf, unsigned int len,
- unsigned int block_id);
-int hv_register_block_invalidate(struct pci_dev *dev, void *context,
- void (*block_invalidate)(void *context,
- u64 block_mask));
+
+int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len,
+ unsigned int block_id, unsigned int *bytes_returned);
+int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len,
+ unsigned int block_id);
+int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context,
+ void (*block_invalidate)(void *context,
+ u64 block_mask));
+
+struct hyperv_pci_block_ops {
+ int (*read_block)(struct pci_dev *dev, void *buf, unsigned int buf_len,
+ unsigned int block_id, unsigned int *bytes_returned);
+ int (*write_block)(struct pci_dev *dev, void *buf, unsigned int len,
+ unsigned int block_id);
+ int (*reg_blk_invalidate)(struct pci_dev *dev, void *context,
+ void (*block_invalidate)(void *context,
+ u64 block_mask));
+};
+
+extern struct hyperv_pci_block_ops hvpci_block_ops;
+
#endif /* _HYPERV_H */
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH bpf-next 2/4] selftests/bpf: test_progs: test__skip
From: Andrii Nakryiko @ 2019-08-14 19:22 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Networking, bpf, David S. Miller, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <20190814164742.208909-3-sdf@google.com>
On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
>
> Export test__skip() to indicate skipped tests and use it in
> test_send_signal_nmi().
>
> Cc: Andrii Nakryiko <andriin@fb.com>
> Signed-off-by: Stanislav Fomichev <sdf@google.com>
> ---
For completeness, we should probably also support test__skip_subtest()
eventually, but it's fine until we don't have a use case.
Acked-by: Andrii Nakryiko <andriin@fb.com>
> tools/testing/selftests/bpf/prog_tests/send_signal.c | 1 +
> tools/testing/selftests/bpf/test_progs.c | 9 +++++++--
> tools/testing/selftests/bpf/test_progs.h | 2 ++
> 3 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> index 1575f0a1f586..40c2c5efdd3e 100644
> --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
> +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> @@ -204,6 +204,7 @@ static int test_send_signal_nmi(void)
> if (errno == ENOENT) {
> printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
> __func__);
> + test__skip();
> return 0;
> }
> /* Let the test fail with a more informative message */
> diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> index 1a7a2a0c0a11..1993f2ce0d23 100644
> --- a/tools/testing/selftests/bpf/test_progs.c
> +++ b/tools/testing/selftests/bpf/test_progs.c
> @@ -121,6 +121,11 @@ void test__force_log() {
> env.test->force_log = true;
> }
>
> +void test__skip(void)
> +{
> + env.skip_cnt++;
> +}
> +
> struct ipv4_packet pkt_v4 = {
> .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> .iph.ihl = 5,
> @@ -535,8 +540,8 @@ int main(int argc, char **argv)
> test->test_name);
> }
> stdio_restore();
> - printf("Summary: %d/%d PASSED, %d FAILED\n",
> - env.succ_cnt, env.sub_succ_cnt, env.fail_cnt);
> + printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
> + env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
>
> free(env.test_selector.num_set);
> free(env.subtest_selector.num_set);
> diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> index 37d427f5a1e5..9defd35cb6c0 100644
> --- a/tools/testing/selftests/bpf/test_progs.h
> +++ b/tools/testing/selftests/bpf/test_progs.h
> @@ -64,6 +64,7 @@ struct test_env {
> int succ_cnt; /* successful tests */
> int sub_succ_cnt; /* successful sub-tests */
> int fail_cnt; /* total failed tests + sub-tests */
> + int skip_cnt; /* skipped tests */
> };
>
> extern int error_cnt;
> @@ -72,6 +73,7 @@ extern struct test_env env;
>
> extern void test__force_log();
> extern bool test__start_subtest(const char *name);
> +extern void test__skip(void);
>
> #define MAGIC_BYTES 123
>
> --
> 2.23.0.rc1.153.gdeed80330f-goog
>
^ permalink raw reply
* Re: [PATCH bpf-next 2/4] selftests/bpf: test_progs: test__skip
From: Andrii Nakryiko @ 2019-08-14 19:30 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Networking, bpf, David S. Miller, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <CAEf4BzZR12JgbSvBqS7LMZjLcsneVDfFL9XyZdi3gtneyA9X9g@mail.gmail.com>
On Wed, Aug 14, 2019 at 12:22 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
> >
> > Export test__skip() to indicate skipped tests and use it in
> > test_send_signal_nmi().
> >
> > Cc: Andrii Nakryiko <andriin@fb.com>
> > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > ---
>
> For completeness, we should probably also support test__skip_subtest()
> eventually, but it's fine until we don't have a use case.
Hm.. so I think we don't need separate test__skip_subtest().
test__skip() should skip either test or sub-test, depending on which
context we are running in. So maybe just make sure this is handled
correctly?
>
> Acked-by: Andrii Nakryiko <andriin@fb.com>
>
> > tools/testing/selftests/bpf/prog_tests/send_signal.c | 1 +
> > tools/testing/selftests/bpf/test_progs.c | 9 +++++++--
> > tools/testing/selftests/bpf/test_progs.h | 2 ++
> > 3 files changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > index 1575f0a1f586..40c2c5efdd3e 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > @@ -204,6 +204,7 @@ static int test_send_signal_nmi(void)
> > if (errno == ENOENT) {
> > printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
> > __func__);
> > + test__skip();
> > return 0;
> > }
> > /* Let the test fail with a more informative message */
> > diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> > index 1a7a2a0c0a11..1993f2ce0d23 100644
> > --- a/tools/testing/selftests/bpf/test_progs.c
> > +++ b/tools/testing/selftests/bpf/test_progs.c
> > @@ -121,6 +121,11 @@ void test__force_log() {
> > env.test->force_log = true;
> > }
> >
> > +void test__skip(void)
> > +{
> > + env.skip_cnt++;
> > +}
> > +
> > struct ipv4_packet pkt_v4 = {
> > .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> > .iph.ihl = 5,
> > @@ -535,8 +540,8 @@ int main(int argc, char **argv)
> > test->test_name);
> > }
> > stdio_restore();
> > - printf("Summary: %d/%d PASSED, %d FAILED\n",
> > - env.succ_cnt, env.sub_succ_cnt, env.fail_cnt);
> > + printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
So because some sub-tests might be skipped, while others will be
running, let's keep output consistent with SUCCESS and use
<test>/<subtests> format for SKIPPED as well?
> > + env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
> >
> > free(env.test_selector.num_set);
> > free(env.subtest_selector.num_set);
> > diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> > index 37d427f5a1e5..9defd35cb6c0 100644
> > --- a/tools/testing/selftests/bpf/test_progs.h
> > +++ b/tools/testing/selftests/bpf/test_progs.h
> > @@ -64,6 +64,7 @@ struct test_env {
> > int succ_cnt; /* successful tests */
> > int sub_succ_cnt; /* successful sub-tests */
> > int fail_cnt; /* total failed tests + sub-tests */
> > + int skip_cnt; /* skipped tests */
> > };
> >
> > extern int error_cnt;
> > @@ -72,6 +73,7 @@ extern struct test_env env;
> >
> > extern void test__force_log();
> > extern bool test__start_subtest(const char *name);
> > +extern void test__skip(void);
> >
> > #define MAGIC_BYTES 123
> >
> > --
> > 2.23.0.rc1.153.gdeed80330f-goog
> >
^ permalink raw reply
* Re: [PATCH bpf-next 3/4] selftests/bpf: test_progs: remove global fail/success counts
From: Andrii Nakryiko @ 2019-08-14 19:47 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Networking, bpf, David S. Miller, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <20190814164742.208909-4-sdf@google.com>
On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
>
> Now that we have a global per-test/per-environment state, there
> is no longer the need to have global fail/success counters
> (and there is no need to save/get the diff before/after the
> test).
>
> Cc: Andrii Nakryiko <andriin@fb.com>
> Signed-off-by: Stanislav Fomichev <sdf@google.com>
> ---
> .../selftests/bpf/prog_tests/bpf_obj_id.c | 2 +-
> .../bpf/prog_tests/bpf_verif_scale.c | 10 +---
> .../selftests/bpf/prog_tests/flow_dissector.c | 2 +-
> .../bpf/prog_tests/get_stack_raw_tp.c | 2 +-
> .../selftests/bpf/prog_tests/global_data.c | 10 ++--
> .../selftests/bpf/prog_tests/l4lb_all.c | 4 +-
> .../selftests/bpf/prog_tests/map_lock.c | 8 +--
> .../selftests/bpf/prog_tests/pkt_access.c | 2 +-
> .../selftests/bpf/prog_tests/pkt_md_access.c | 2 +-
> .../bpf/prog_tests/queue_stack_map.c | 4 +-
> .../bpf/prog_tests/reference_tracking.c | 2 +-
> .../selftests/bpf/prog_tests/spinlock.c | 2 +-
> .../selftests/bpf/prog_tests/stacktrace_map.c | 2 +-
> .../bpf/prog_tests/stacktrace_map_raw_tp.c | 2 +-
> .../bpf/prog_tests/task_fd_query_rawtp.c | 2 +-
> .../bpf/prog_tests/task_fd_query_tp.c | 2 +-
> .../selftests/bpf/prog_tests/tcp_estats.c | 2 +-
> tools/testing/selftests/bpf/prog_tests/xdp.c | 2 +-
> .../bpf/prog_tests/xdp_adjust_tail.c | 2 +-
> .../selftests/bpf/prog_tests/xdp_noinline.c | 4 +-
> tools/testing/selftests/bpf/test_progs.c | 55 ++++++++-----------
> tools/testing/selftests/bpf/test_progs.h | 26 +++++++--
> 22 files changed, 75 insertions(+), 74 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c b/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
> index fb5840a62548..f57e0c625de3 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
> @@ -49,7 +49,7 @@ void test_bpf_obj_id(void)
> * to load.
> */
> if (err)
> - error_cnt++;
> + test__fail();
> assert(!err);
>
> /* Insert a magic value to the map */
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
> index 1a1eae356f81..217988243077 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
> @@ -28,8 +28,6 @@ static int check_load(const char *file, enum bpf_prog_type type)
> attr.prog_flags = BPF_F_TEST_RND_HI32;
> err = bpf_prog_load_xattr(&attr, &obj, &prog_fd);
> bpf_object__close(obj);
> - if (err)
> - error_cnt++;
> return err;
> }
>
> @@ -105,12 +103,8 @@ void test_bpf_verif_scale(void)
> continue;
>
> err = check_load(test->file, test->attach_type);
> - if (test->fails) { /* expected to fail */
> - if (err)
> - error_cnt--;
> - else
> - error_cnt++;
> - }
> + if (err && !test->fails)
> + test__fail();
> }
>
> if (env.verifier_stats)
> diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
> index 6892b88ae065..e9d882c05ded 100644
> --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
> +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
> @@ -453,7 +453,7 @@ void test_flow_dissector(void)
> err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
> "jmp_table", "last_dissection", &prog_fd, &keys_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
> index 3d59b3c841fe..afc60f62e2a8 100644
> --- a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
> +++ b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
> @@ -137,7 +137,7 @@ void test_get_stack_raw_tp(void)
>
> goto close_prog_noerr;
> close_prog:
> - error_cnt++;
> + test__fail();
> close_prog_noerr:
> if (!IS_ERR_OR_NULL(link))
> bpf_link__destroy(link);
> diff --git a/tools/testing/selftests/bpf/prog_tests/global_data.c b/tools/testing/selftests/bpf/prog_tests/global_data.c
> index d011079fb0bf..db13bfee6bb9 100644
> --- a/tools/testing/selftests/bpf/prog_tests/global_data.c
> +++ b/tools/testing/selftests/bpf/prog_tests/global_data.c
> @@ -8,7 +8,7 @@ static void test_global_data_number(struct bpf_object *obj, __u32 duration)
>
> map_fd = bpf_find_map(__func__, obj, "result_number");
> if (map_fd < 0) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> @@ -45,7 +45,7 @@ static void test_global_data_string(struct bpf_object *obj, __u32 duration)
>
> map_fd = bpf_find_map(__func__, obj, "result_string");
> if (map_fd < 0) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> @@ -82,7 +82,7 @@ static void test_global_data_struct(struct bpf_object *obj, __u32 duration)
>
> map_fd = bpf_find_map(__func__, obj, "result_struct");
> if (map_fd < 0) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> @@ -113,13 +113,13 @@ static void test_global_data_rdonly(struct bpf_object *obj, __u32 duration)
>
> map = bpf_object__find_map_by_name(obj, "test_glo.rodata");
> if (!map || !bpf_map__is_internal(map)) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> map_fd = bpf_map__fd(map);
> if (map_fd < 0) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c
> index 20ddca830e68..724bb40de1f8 100644
> --- a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c
> +++ b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c
> @@ -31,7 +31,7 @@ static void test_l4lb(const char *file)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> @@ -73,7 +73,7 @@ static void test_l4lb(const char *file)
> pkts += stats[i].pkts;
> }
> if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
> - error_cnt++;
> + test__fail();
> printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
> }
> out:
> diff --git a/tools/testing/selftests/bpf/prog_tests/map_lock.c b/tools/testing/selftests/bpf/prog_tests/map_lock.c
> index ee99368c595c..12123ff1f31f 100644
> --- a/tools/testing/selftests/bpf/prog_tests/map_lock.c
> +++ b/tools/testing/selftests/bpf/prog_tests/map_lock.c
> @@ -10,12 +10,12 @@ static void *parallel_map_access(void *arg)
> err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK);
> if (err) {
> printf("lookup failed\n");
> - error_cnt++;
> + test__fail();
> goto out;
> }
> if (vars[0] != 0) {
> printf("lookup #%d var[0]=%d\n", i, vars[0]);
> - error_cnt++;
> + test__fail();
> goto out;
> }
> rnd = vars[1];
> @@ -24,7 +24,7 @@ static void *parallel_map_access(void *arg)
> continue;
> printf("lookup #%d var[1]=%d var[%d]=%d\n",
> i, rnd, j, vars[j]);
> - error_cnt++;
> + test__fail();
> goto out;
> }
> }
> @@ -69,7 +69,7 @@ void test_map_lock(void)
> ret == (void *)&map_fd[i - 4]);
> goto close_prog_noerr;
> close_prog:
> - error_cnt++;
> + test__fail();
> close_prog_noerr:
> bpf_object__close(obj);
> }
> diff --git a/tools/testing/selftests/bpf/prog_tests/pkt_access.c b/tools/testing/selftests/bpf/prog_tests/pkt_access.c
> index 4ecfd721a044..9ef4e4ffb379 100644
> --- a/tools/testing/selftests/bpf/prog_tests/pkt_access.c
> +++ b/tools/testing/selftests/bpf/prog_tests/pkt_access.c
> @@ -10,7 +10,7 @@ void test_pkt_access(void)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c b/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c
> index ac0d43435806..c354b9d21f4f 100644
> --- a/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c
> +++ b/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c
> @@ -10,7 +10,7 @@ void test_pkt_md_access(void)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c b/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
> index e60cd5ff1f55..48a8cd144bd1 100644
> --- a/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
> +++ b/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
> @@ -28,7 +28,7 @@ static void test_queue_stack_map_by_type(int type)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> @@ -44,7 +44,7 @@ static void test_queue_stack_map_by_type(int type)
> for (i = 0; i < MAP_SIZE; i++) {
> err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0);
> if (err) {
> - error_cnt++;
> + test__fail();
> goto out;
> }
> }
> diff --git a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c
> index 4a4f428d1a78..f6987e3dd28c 100644
> --- a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c
> +++ b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c
> @@ -11,7 +11,7 @@ void test_reference_tracking(void)
>
> obj = bpf_object__open(file);
> if (IS_ERR(obj)) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/spinlock.c b/tools/testing/selftests/bpf/prog_tests/spinlock.c
> index 114ebe6a438e..e843336713e8 100644
> --- a/tools/testing/selftests/bpf/prog_tests/spinlock.c
> +++ b/tools/testing/selftests/bpf/prog_tests/spinlock.c
> @@ -23,7 +23,7 @@ void test_spinlock(void)
> ret == (void *)&prog_fd);
> goto close_prog_noerr;
> close_prog:
> - error_cnt++;
> + test__fail();
> close_prog_noerr:
> bpf_object__close(obj);
> }
> diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
> index fc539335c5b3..9dba1cc3da60 100644
> --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
> +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
> @@ -70,7 +70,7 @@ void test_stacktrace_map(void)
>
> goto disable_pmu_noerr;
> disable_pmu:
> - error_cnt++;
> + test__fail();
> disable_pmu_noerr:
> bpf_link__destroy(link);
> close_prog:
> diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c
> index fbfa8e76cf63..4e7cf2e663f7 100644
> --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c
> +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c
> @@ -60,7 +60,7 @@ void test_stacktrace_map_raw_tp(void)
>
> goto close_prog_noerr;
> close_prog:
> - error_cnt++;
> + test__fail();
> close_prog_noerr:
> if (!IS_ERR_OR_NULL(link))
> bpf_link__destroy(link);
> diff --git a/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c b/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c
> index 958a3d88de99..d9ad1aa8a026 100644
> --- a/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c
> +++ b/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c
> @@ -72,7 +72,7 @@ void test_task_fd_query_rawtp(void)
>
> goto close_prog_noerr;
> close_prog:
> - error_cnt++;
> + test__fail();
> close_prog_noerr:
> bpf_object__close(obj);
> }
> diff --git a/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c b/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c
> index f9b70e81682b..76209f2386c8 100644
> --- a/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c
> +++ b/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c
> @@ -68,7 +68,7 @@ static void test_task_fd_query_tp_core(const char *probe_name,
> close_pmu:
> close(pmu_fd);
> close_prog:
> - error_cnt++;
> + test__fail();
> close_prog_noerr:
> bpf_object__close(obj);
> }
> diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_estats.c b/tools/testing/selftests/bpf/prog_tests/tcp_estats.c
> index bb8759d69099..e241e5d7c71f 100644
> --- a/tools/testing/selftests/bpf/prog_tests/tcp_estats.c
> +++ b/tools/testing/selftests/bpf/prog_tests/tcp_estats.c
> @@ -11,7 +11,7 @@ void test_tcp_estats(void)
> err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
> CHECK(err, "", "err %d errno %d\n", err, errno);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/xdp.c b/tools/testing/selftests/bpf/prog_tests/xdp.c
> index a74167289545..7c9f89fa1d02 100644
> --- a/tools/testing/selftests/bpf/prog_tests/xdp.c
> +++ b/tools/testing/selftests/bpf/prog_tests/xdp.c
> @@ -17,7 +17,7 @@ void test_xdp(void)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
> index 922aa0a19764..a479a3303c3b 100644
> --- a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
> +++ b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
> @@ -11,7 +11,7 @@ void test_xdp_adjust_tail(void)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c
> index 15f7c272edb0..10bef9d5ab81 100644
> --- a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c
> +++ b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c
> @@ -32,7 +32,7 @@ void test_xdp_noinline(void)
>
> err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
> if (err) {
> - error_cnt++;
> + test__fail();
> return;
> }
>
> @@ -74,7 +74,7 @@ void test_xdp_noinline(void)
> pkts += stats[i].pkts;
> }
> if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
> - error_cnt++;
> + test__fail();
> printf("test_xdp_noinline:FAIL:stats %lld %lld\n",
> bytes, pkts);
> }
> diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> index 1993f2ce0d23..ad90e45768ce 100644
> --- a/tools/testing/selftests/bpf/test_progs.c
> +++ b/tools/testing/selftests/bpf/test_progs.c
> @@ -8,24 +8,6 @@
>
> /* defined in test_progs.h */
> struct test_env env;
> -int error_cnt, pass_cnt;
> -
> -struct prog_test_def {
> - const char *test_name;
> - int test_num;
> - void (*run_test)(void);
> - bool force_log;
> - int pass_cnt;
> - int error_cnt;
> - bool tested;
> -
> - const char *subtest_name;
> - int subtest_num;
> -
> - /* store counts before subtest started */
> - int old_pass_cnt;
> - int old_error_cnt;
> -};
>
> static bool should_run(struct test_selector *sel, int num, const char *name)
> {
> @@ -74,14 +56,14 @@ static const char *test_status_string(bool success)
> void test__end_subtest()
> {
> struct prog_test_def *test = env.test;
> - int sub_error_cnt = error_cnt - test->old_error_cnt;
> + int sub_fail_cnt = test->fail_cnt - test->old_fail_cnt;
>
> - if (sub_error_cnt)
> - env.fail_cnt++;
> + if (sub_fail_cnt)
> + test->fail_cnt++;
> else
> env.sub_succ_cnt++;
>
> - dump_test_log(test, sub_error_cnt);
> + dump_test_log(test, sub_fail_cnt);
>
> fprintf(env.stdout, "#%3d/%-3d %4s %s:%s\n",
> test->test_num, test->subtest_num,
> @@ -111,8 +93,8 @@ bool test__start_subtest(const char *name)
> return false;
>
> test->subtest_name = name;
> - env.test->old_pass_cnt = pass_cnt;
> - env.test->old_error_cnt = error_cnt;
> + env.test->old_succ_cnt = env.test->succ_cnt;
> + env.test->old_fail_cnt = env.test->fail_cnt;
>
> return true;
> }
> @@ -126,6 +108,19 @@ void test__skip(void)
> env.skip_cnt++;
> }
>
> +void __test__fail(const char *file, int line)
> +{
> + if (env.test->subtest_name)
> + fprintf(stderr, "%s:%s failed at %s:%d, errno=%d\n",
Nit: let's keep <test>/<subtest> convention here as well?
Failure doesn't always set errno, this will be quite confusing
sometimes. Especially for higher-level libbpf APIs, which don't set
errno at all.
If test wants to log additional information, let it do it explicitly.
Also, _CHECK already logs error message, so this is going to be
double-verbose for typical case. I'd say let's drop these error
messages and instead slightly extend _CHECK one with line number (it
already logs func name).
> + env.test->test_name, env.test->subtest_name,
> + file, line, errno);
> + else
> + fprintf(stderr, "%s failed at %s:%d, errno=%d\n",
> + env.test->test_name, file, line, errno);
> +
> + env.test->fail_cnt++;
> +}
> +
> struct ipv4_packet pkt_v4 = {
> .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> .iph.ihl = 5,
> @@ -150,7 +145,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
> map = bpf_object__find_map_by_name(obj, name);
> if (!map) {
> printf("%s:FAIL:map '%s' not found\n", test, name);
> - error_cnt++;
> + test__fail();
> return -1;
> }
> return bpf_map__fd(map);
> @@ -509,8 +504,6 @@ int main(int argc, char **argv)
> stdio_hijack();
> for (i = 0; i < prog_test_cnt; i++) {
> struct prog_test_def *test = &prog_test_defs[i];
> - int old_pass_cnt = pass_cnt;
> - int old_error_cnt = error_cnt;
>
> env.test = test;
> test->test_num = i + 1;
> @@ -525,14 +518,12 @@ int main(int argc, char **argv)
> test__end_subtest();
>
> test->tested = true;
> - test->pass_cnt = pass_cnt - old_pass_cnt;
> - test->error_cnt = error_cnt - old_error_cnt;
> - if (test->error_cnt)
> + if (test->fail_cnt)
> env.fail_cnt++;
> else
> env.succ_cnt++;
>
> - dump_test_log(test, test->error_cnt);
> + dump_test_log(test, test->fail_cnt);
>
> fprintf(env.stdout, "#%3d %4s %s\n",
> test->test_num,
> @@ -546,5 +537,5 @@ int main(int argc, char **argv)
> free(env.test_selector.num_set);
> free(env.subtest_selector.num_set);
>
> - return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> + return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> }
> diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> index 9defd35cb6c0..7b05921784a4 100644
> --- a/tools/testing/selftests/bpf/test_progs.h
> +++ b/tools/testing/selftests/bpf/test_progs.h
> @@ -38,7 +38,23 @@ typedef __u16 __sum16;
> #include "trace_helpers.h"
> #include "flow_dissector_load.h"
>
> -struct prog_test_def;
> +struct prog_test_def {
> + const char *test_name;
> + int test_num;
> + void (*run_test)(void);
> + bool force_log;
> + bool tested;
> +
> + const char *subtest_name;
> + int subtest_num;
> +
> + int succ_cnt;
> + int fail_cnt;
So I'm neutral on this rename, I even considered it myself initially.
But keep in mind, that succ/fail in env means number of tests, while
test->succ/fail means number of assertions. We don't report total
number of failed checks anymore, so it doesn't matter, but if we ever
want to keep track of that at env level, it will be very confusing and
inconvenient.
> +
> + /* store counts before subtest started */
> + int old_succ_cnt;
> + int old_fail_cnt;
> +};
Did you move it here just to access env.test->succ_cnt in _CHECK()?
Maybe add test__success() counterpart to test__fail() instead?
>
> struct test_selector {
> const char *name;
> @@ -67,13 +83,13 @@ struct test_env {
> int skip_cnt; /* skipped tests */
> };
>
> -extern int error_cnt;
> -extern int pass_cnt;
> extern struct test_env env;
>
> extern void test__force_log();
> extern bool test__start_subtest(const char *name);
> extern void test__skip(void);
> +#define test__fail() __test__fail(__FILE__, __LINE__)
> +extern void __test__fail(const char *file, int line);
Given my comment above about too verbose logging, I'd say let's keep
this simple and have just
extern void test__fail()
And let _CHECK log file:line.
>
> #define MAGIC_BYTES 123
>
> @@ -96,11 +112,11 @@ extern struct ipv6_packet pkt_v6;
> #define _CHECK(condition, tag, duration, format...) ({ \
> int __ret = !!(condition); \
> if (__ret) { \
> - error_cnt++; \
> + test__fail(); \
> printf("%s:FAIL:%s ", __func__, tag); \
> printf(format); \
> } else { \
> - pass_cnt++; \
> + env.test->succ_cnt++; \
> printf("%s:PASS:%s %d nsec\n", \
> __func__, tag, duration); \
> } \
> --
> 2.23.0.rc1.153.gdeed80330f-goog
>
^ permalink raw reply
* Re: [PATCH bpf-next 4/4] selftests/bpf: test_progs: remove asserts from subtests
From: Andrii Nakryiko @ 2019-08-14 19:52 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Networking, bpf, David S. Miller, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <20190814164742.208909-5-sdf@google.com>
On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
>
> Otherwise they can bring the whole process down.
>
> Cc: Andrii Nakryiko <andriin@fb.com>
> Signed-off-by: Stanislav Fomichev <sdf@google.com>
> ---
This is probably why you added all that extra logging in __test__fail(), right?
So had a low-priority TODO item to add another CHECK()-like macro that
would only report failure (but won't bump/log success). Seems like
this is something that would be useful for these asserts?
What do you think about either QCHECK() (for "quiet" check) or surely
we can also do ASSERT (but it's less obvious that it won't log success
and it's also not obvious that it won't actually terminate test
immediately).
Then inside that QCHECK() you can log file:line number, similar to
CHECK(), but only for failure case.
Thoughts?
^ permalink raw reply
* Re: [PATCH bpf-next 2/4] selftests/bpf: test_progs: test__skip
From: Stanislav Fomichev @ 2019-08-14 19:53 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Stanislav Fomichev, Networking, bpf, David S. Miller,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <CAEf4BzaE-KiW1Xt049A4s25YiaLeTH3yhgahwLUdpXNjF1sVpA@mail.gmail.com>
On 08/14, Andrii Nakryiko wrote:
> On Wed, Aug 14, 2019 at 12:22 PM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
> > >
> > > Export test__skip() to indicate skipped tests and use it in
> > > test_send_signal_nmi().
> > >
> > > Cc: Andrii Nakryiko <andriin@fb.com>
> > > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > > ---
> >
> > For completeness, we should probably also support test__skip_subtest()
> > eventually, but it's fine until we don't have a use case.
>
> Hm.. so I think we don't need separate test__skip_subtest().
> test__skip() should skip either test or sub-test, depending on which
> context we are running in. So maybe just make sure this is handled
> correctly?
Do we care if it's a test or a subtest skip? My motivation was to
have a counter that can be examined to make sure we have a full test
coverage, so when people run the tests they can be sure that nothing
is skipped due to missing config or something else.
Let me know if you see a value in highlighting test vs subtest skip.
Other related question is: should we do verbose output in case
of a skip? Right now we don't do it.
> >
> > Acked-by: Andrii Nakryiko <andriin@fb.com>
> >
> > > tools/testing/selftests/bpf/prog_tests/send_signal.c | 1 +
> > > tools/testing/selftests/bpf/test_progs.c | 9 +++++++--
> > > tools/testing/selftests/bpf/test_progs.h | 2 ++
> > > 3 files changed, 10 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > > index 1575f0a1f586..40c2c5efdd3e 100644
> > > --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > > +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > > @@ -204,6 +204,7 @@ static int test_send_signal_nmi(void)
> > > if (errno == ENOENT) {
> > > printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
> > > __func__);
> > > + test__skip();
> > > return 0;
> > > }
> > > /* Let the test fail with a more informative message */
> > > diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> > > index 1a7a2a0c0a11..1993f2ce0d23 100644
> > > --- a/tools/testing/selftests/bpf/test_progs.c
> > > +++ b/tools/testing/selftests/bpf/test_progs.c
> > > @@ -121,6 +121,11 @@ void test__force_log() {
> > > env.test->force_log = true;
> > > }
> > >
> > > +void test__skip(void)
> > > +{
> > > + env.skip_cnt++;
> > > +}
> > > +
> > > struct ipv4_packet pkt_v4 = {
> > > .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> > > .iph.ihl = 5,
> > > @@ -535,8 +540,8 @@ int main(int argc, char **argv)
> > > test->test_name);
> > > }
> > > stdio_restore();
> > > - printf("Summary: %d/%d PASSED, %d FAILED\n",
> > > - env.succ_cnt, env.sub_succ_cnt, env.fail_cnt);
> > > + printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
>
> So because some sub-tests might be skipped, while others will be
> running, let's keep output consistent with SUCCESS and use
> <test>/<subtests> format for SKIPPED as well?
>
> > > + env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
> > >
> > > free(env.test_selector.num_set);
> > > free(env.subtest_selector.num_set);
> > > diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> > > index 37d427f5a1e5..9defd35cb6c0 100644
> > > --- a/tools/testing/selftests/bpf/test_progs.h
> > > +++ b/tools/testing/selftests/bpf/test_progs.h
> > > @@ -64,6 +64,7 @@ struct test_env {
> > > int succ_cnt; /* successful tests */
> > > int sub_succ_cnt; /* successful sub-tests */
> > > int fail_cnt; /* total failed tests + sub-tests */
> > > + int skip_cnt; /* skipped tests */
> > > };
> > >
> > > extern int error_cnt;
> > > @@ -72,6 +73,7 @@ extern struct test_env env;
> > >
> > > extern void test__force_log();
> > > extern bool test__start_subtest(const char *name);
> > > +extern void test__skip(void);
> > >
> > > #define MAGIC_BYTES 123
> > >
> > > --
> > > 2.23.0.rc1.153.gdeed80330f-goog
> > >
^ permalink raw reply
* Re: [PATCH bpf-next 1/3] libbpf: add asm/unistd.h to xsk to get __NR_mmap2
From: Ivan Khoronzhuk @ 2019-08-14 19:54 UTC (permalink / raw)
To: Björn Töpel
Cc: Andrii Nakryiko, Magnus Karlsson, Björn Töpel,
David S. Miller, Jesper Dangaard Brouer, john fastabend,
Jakub Kicinski, Daniel Borkmann, Networking, bpf, Xdp, open list
In-Reply-To: <CAJ+HfNiqu7WEoBFnfK3znU4tVyAmpPVabTjTSKH1ZVo2W1rrXg@mail.gmail.com>
On Wed, Aug 14, 2019 at 03:32:24PM +0200, Björn Töpel wrote:
>On Wed, 14 Aug 2019 at 13:57, Ivan Khoronzhuk
><ivan.khoronzhuk@linaro.org> wrote:
>>
>> On Wed, Aug 14, 2019 at 12:24:05PM +0300, Ivan Khoronzhuk wrote:
>> >On Tue, Aug 13, 2019 at 04:38:13PM -0700, Andrii Nakryiko wrote:
>> >
>> >Hi, Andrii
>> >
>> >>On Tue, Aug 13, 2019 at 3:24 AM Ivan Khoronzhuk
>> >><ivan.khoronzhuk@linaro.org> wrote:
>> >>>
>> >>>That's needed to get __NR_mmap2 when mmap2 syscall is used.
>> >>>
>> >>>Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
>> >>>---
>> >>> tools/lib/bpf/xsk.c | 1 +
>> >>> 1 file changed, 1 insertion(+)
>> >>>
>> >>>diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
>> >>>index 5007b5d4fd2c..f2fc40f9804c 100644
>> >>>--- a/tools/lib/bpf/xsk.c
>> >>>+++ b/tools/lib/bpf/xsk.c
>> >>>@@ -12,6 +12,7 @@
>> >>> #include <stdlib.h>
>> >>> #include <string.h>
>> >>> #include <unistd.h>
>> >>>+#include <asm/unistd.h>
>> >>
>> >>asm/unistd.h is not present in Github libbpf projection. Is there any
>> >
>> >Look on includes from
>> >tools/lib/bpf/libpf.c
>> >tools/lib/bpf/bpf.c
>> >
>> >That's how it's done... Copping headers to arch/arm will not
>> >solve this, it includes both of them anyway, and anyway it needs
>> >asm/unistd.h inclusion here, only because xsk.c needs __NR_*
>> >
>> >
>>
>> There is one more radical solution for this I can send, but I'm not sure how it
>> can impact on other syscals/arches...
>>
>> Looks like:
>>
>>
>> diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
>> index 9312066a1ae3..8b2f8ff7ce44 100644
>> --- a/tools/lib/bpf/Makefile
>> +++ b/tools/lib/bpf/Makefile
>> @@ -113,6 +113,7 @@ override CFLAGS += -Werror -Wall
>> override CFLAGS += -fPIC
>> override CFLAGS += $(INCLUDES)
>> override CFLAGS += -fvisibility=hidden
>> +override CFLAGS += -D_FILE_OFFSET_BITS=64
>>
>
>Hmm, isn't this glibc-ism? Does is it work for, say, musl or bionic?
>
>If this is portable, and works on 32-, and 64-bit archs, I'm happy
>with the patch. :-)
https://users.suse.com/~aj/linux_lfs.html
BIONIС
======
https://android.googlesource.com/platform/bionic
So, LFS is in bionic since Fri Feb 6 22:28:49 2015
68dc20d41193831a94df04b994ff2f601dd38d10
Author: Elliott Hughes <enh@google.com>
Implement _FILE_OFFSET_BITS (mostly)
MUSL
====
I took here: git@github.com:kraj/musl.git
With musl situation is a little different, seems like, it provides
64bit off_t by default
#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
#define lseek64 lseek
#define pread64 pread
#define pwrite64 pwrite
#define truncate64 truncate
#define ftruncate64 ftruncate
#define lockf64 lockf
#define off64_t off_t
#endif
and
/* If _GNU_SOURCE was defined by the user, turn on all the other features. */
#ifdef _GNU_SOURCE
# undef _ISOC95_SOURCE
# define _ISOC95_SOURCE 1
# undef _ISOC99_SOURCE
# define _ISOC99_SOURCE 1
# undef _ISOC11_SOURCE
# define _ISOC11_SOURCE 1
# undef _POSIX_SOURCE
# define _POSIX_SOURCE 1
# undef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200809L
# undef _XOPEN_SOURCE
# define _XOPEN_SOURCE 700
# undef _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED 1
# undef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE 1
# undef _DEFAULT_SOURCE
# define _DEFAULT_SOURCE 1
# undef _ATFILE_SOURCE
# define _ATFILE_SOURCE 1
#endif
So shouldn't be issuse.
64 ARCHES
=========
Should also work, if grep on _FILE_OFFSET_BITS tool:
./lib/api/Makefile:CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
./lib/subcmd/Makefile:CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
So, it's used already and no problems.
But here one moment, _LARGEFILE64_SOURCE is also defined, probably for MUSL
(despite it's defined anyway) just to be sure.
So, in Makefile, for sure, will be:
override CFLAGS += -D_FILE_OFFSET_BITS=64
verride CFLAGS += -D_LARGEFILE64_SOURCE
--
Regards,
Ivan Khoronzhuk
^ permalink raw reply
* Re: [PATCH bpf-next 1/3] libbpf: add asm/unistd.h to xsk to get __NR_mmap2
From: Andrii Nakryiko @ 2019-08-14 19:56 UTC (permalink / raw)
To: Andrii Nakryiko, Magnus Karlsson, Björn Töpel,
David S. Miller, Jesper Dangaard Brouer, john fastabend,
Jakub Kicinski, Daniel Borkmann, Networking, bpf, xdp-newbies,
open list
In-Reply-To: <20190814092403.GA4142@khorivan>
On Wed, Aug 14, 2019 at 2:24 AM Ivan Khoronzhuk
<ivan.khoronzhuk@linaro.org> wrote:
>
> On Tue, Aug 13, 2019 at 04:38:13PM -0700, Andrii Nakryiko wrote:
>
> Hi, Andrii
>
> >On Tue, Aug 13, 2019 at 3:24 AM Ivan Khoronzhuk
> ><ivan.khoronzhuk@linaro.org> wrote:
> >>
> >> That's needed to get __NR_mmap2 when mmap2 syscall is used.
> >>
> >> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
> >> ---
> >> tools/lib/bpf/xsk.c | 1 +
> >> 1 file changed, 1 insertion(+)
> >>
> >> diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
> >> index 5007b5d4fd2c..f2fc40f9804c 100644
> >> --- a/tools/lib/bpf/xsk.c
> >> +++ b/tools/lib/bpf/xsk.c
> >> @@ -12,6 +12,7 @@
> >> #include <stdlib.h>
> >> #include <string.h>
> >> #include <unistd.h>
> >> +#include <asm/unistd.h>
> >
> >asm/unistd.h is not present in Github libbpf projection. Is there any
>
> Look on includes from
> tools/lib/bpf/libpf.c
> tools/lib/bpf/bpf.c
>
Yeah, sorry for the noise. I missed that this is system header that's
expected to be present, not internal kernel header, parts of which we
need to re-implement for Github projection. Never mind my concerns.
> That's how it's done... Copping headers to arch/arm will not
> solve this, it includes both of them anyway, and anyway it needs
> asm/unistd.h inclusion here, only because xsk.c needs __NR_*
>
>
> >way to avoid including this header? Generally, libbpf can't easily use
> >all of kernel headers, we need to re-implemented all the extra used
> >stuff for Github version of libbpf, so we try to minimize usage of new
> >headers that are not just plain uapi headers from include/uapi.
>
> Yes I know, it's far away from real number of changes needed.
> I faced enough about this already and kernel headers, especially
> for arm32 it's a bit decency problem. But this patch it's part of
> normal one. I have couple issues despite this normally fixed mmap2
> that is the same even if uapi includes are coppied to tools/arch/arm.
>
> In continuation of kernel headers inclusion and arm build:
>
> For instance, what about this rough "kernel headers" hack:
> https://github.com/ikhorn/af_xdp_stuff/commit/aa645ccca4d844f404ec3c2b27402d4d7848d1b5
>
> or this one related for arm32 only:
> https://github.com/ikhorn/af_xdp_stuff/commit/2c6c6d538605aac39600dcb3c9b66de11c70b963
>
> I have more...
>
> >
> >> #include <arpa/inet.h>
> >> #include <asm/barrier.h>
> >> #include <linux/compiler.h>
> >> --
> >> 2.17.1
> >>
>
> --
> Regards,
> Ivan Khoronzhuk
^ permalink raw reply
* [PATCH net] ibmvnic: Unmap DMA address of TX descriptor buffers after use
From: Thomas Falcon @ 2019-08-14 19:57 UTC (permalink / raw)
To: netdev; +Cc: Thomas Falcon
There's no need to wait until a completion is received to unmap
TX descriptor buffers that have been passed to the hypervisor.
Instead unmap it when the hypervisor call has completed. This patch
avoids the possibility that a buffer will not be unmapped because
a TX completion is lost or mishandled.
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Tested-by: Devesh K. Singh <devesh_singh@in.ibm.com>
Signed-off-by: Thomas Falcon <tlfalcon@linux.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 81a05ea38237..07efa2b40003 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1568,6 +1568,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
(u64)tx_buff->indir_dma,
(u64)num_entries);
+ dma_unmap_single(dev, tx_buff->indir_dma,
+ sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
} else {
tx_buff->num_entries = num_entries;
lpar_rc = send_subcrq(adapter, handle_array[queue_num],
@@ -2788,7 +2790,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
union sub_crq *next;
int index;
int i, j;
- u8 *first;
restart_loop:
while (pending_scrq(adapter, scrq)) {
@@ -2818,14 +2819,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
txbuff->data_dma[j] = 0;
}
- /* if sub_crq was sent indirectly */
- first = &txbuff->indir_arr[0].generic.first;
- if (*first == IBMVNIC_CRQ_CMD) {
- dma_unmap_single(dev, txbuff->indir_dma,
- sizeof(txbuff->indir_arr),
- DMA_TO_DEVICE);
- *first = 0;
- }
if (txbuff->last_frag) {
dev_kfree_skb_any(txbuff->skb);
--
2.16.4
^ permalink raw reply related
* Re: [PATCH bpf-next 2/4] selftests/bpf: test_progs: test__skip
From: Andrii Nakryiko @ 2019-08-14 20:01 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Stanislav Fomichev, Networking, bpf, David S. Miller,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <20190814195330.GL2820@mini-arch>
On Wed, Aug 14, 2019 at 12:53 PM Stanislav Fomichev <sdf@fomichev.me> wrote:
>
> On 08/14, Andrii Nakryiko wrote:
> > On Wed, Aug 14, 2019 at 12:22 PM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
> > > >
> > > > Export test__skip() to indicate skipped tests and use it in
> > > > test_send_signal_nmi().
> > > >
> > > > Cc: Andrii Nakryiko <andriin@fb.com>
> > > > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > > > ---
> > >
> > > For completeness, we should probably also support test__skip_subtest()
> > > eventually, but it's fine until we don't have a use case.
> >
> > Hm.. so I think we don't need separate test__skip_subtest().
> > test__skip() should skip either test or sub-test, depending on which
> > context we are running in. So maybe just make sure this is handled
> > correctly?
> Do we care if it's a test or a subtest skip? My motivation was to
> have a counter that can be examined to make sure we have a full test
> coverage, so when people run the tests they can be sure that nothing
> is skipped due to missing config or something else.
I think we do. We might convert, e.g., test_btf to be one big test
with lots of sub-tests. Some of those might be legitimately skipped.
Having just "1 test skipped" message is not helpful, when there are
170 sub-tests that were not.
>
> Let me know if you see a value in highlighting test vs subtest skip.
>
> Other related question is: should we do verbose output in case
> of a skip? Right now we don't do it.
It might be useful, I guess, especially if it's not too common. But
Alexei is way more picky about stuff like that, so I'd defer to him. I
have no problem with a clean "SKIPPED: <test>/<subtest> (maybe some
reason for skipping here)" message.
>
> > >
> > > Acked-by: Andrii Nakryiko <andriin@fb.com>
> > >
> > > > tools/testing/selftests/bpf/prog_tests/send_signal.c | 1 +
> > > > tools/testing/selftests/bpf/test_progs.c | 9 +++++++--
> > > > tools/testing/selftests/bpf/test_progs.h | 2 ++
> > > > 3 files changed, 10 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > > > index 1575f0a1f586..40c2c5efdd3e 100644
> > > > --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > > > +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
> > > > @@ -204,6 +204,7 @@ static int test_send_signal_nmi(void)
> > > > if (errno == ENOENT) {
> > > > printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
> > > > __func__);
> > > > + test__skip();
> > > > return 0;
> > > > }
> > > > /* Let the test fail with a more informative message */
> > > > diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> > > > index 1a7a2a0c0a11..1993f2ce0d23 100644
> > > > --- a/tools/testing/selftests/bpf/test_progs.c
> > > > +++ b/tools/testing/selftests/bpf/test_progs.c
> > > > @@ -121,6 +121,11 @@ void test__force_log() {
> > > > env.test->force_log = true;
> > > > }
> > > >
> > > > +void test__skip(void)
> > > > +{
> > > > + env.skip_cnt++;
> > > > +}
> > > > +
> > > > struct ipv4_packet pkt_v4 = {
> > > > .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> > > > .iph.ihl = 5,
> > > > @@ -535,8 +540,8 @@ int main(int argc, char **argv)
> > > > test->test_name);
> > > > }
> > > > stdio_restore();
> > > > - printf("Summary: %d/%d PASSED, %d FAILED\n",
> > > > - env.succ_cnt, env.sub_succ_cnt, env.fail_cnt);
> > > > + printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
> >
> > So because some sub-tests might be skipped, while others will be
> > running, let's keep output consistent with SUCCESS and use
> > <test>/<subtests> format for SKIPPED as well?
> >
> > > > + env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
> > > >
> > > > free(env.test_selector.num_set);
> > > > free(env.subtest_selector.num_set);
> > > > diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> > > > index 37d427f5a1e5..9defd35cb6c0 100644
> > > > --- a/tools/testing/selftests/bpf/test_progs.h
> > > > +++ b/tools/testing/selftests/bpf/test_progs.h
> > > > @@ -64,6 +64,7 @@ struct test_env {
> > > > int succ_cnt; /* successful tests */
> > > > int sub_succ_cnt; /* successful sub-tests */
> > > > int fail_cnt; /* total failed tests + sub-tests */
> > > > + int skip_cnt; /* skipped tests */
> > > > };
> > > >
> > > > extern int error_cnt;
> > > > @@ -72,6 +73,7 @@ extern struct test_env env;
> > > >
> > > > extern void test__force_log();
> > > > extern bool test__start_subtest(const char *name);
> > > > +extern void test__skip(void);
> > > >
> > > > #define MAGIC_BYTES 123
> > > >
> > > > --
> > > > 2.23.0.rc1.153.gdeed80330f-goog
> > > >
^ permalink raw reply
* Re: [PATCH bpf-next 3/4] selftests/bpf: test_progs: remove global fail/success counts
From: Stanislav Fomichev @ 2019-08-14 20:07 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Stanislav Fomichev, Networking, bpf, David S. Miller,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <CAEf4BzYNQSQKrDXHvMnFZY+uapU7uou1MnE_YY-QjoBCN3qLrA@mail.gmail.com>
On 08/14, Andrii Nakryiko wrote:
> On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
> >
> > Now that we have a global per-test/per-environment state, there
> > is no longer the need to have global fail/success counters
> > (and there is no need to save/get the diff before/after the
> > test).
> >
> > Cc: Andrii Nakryiko <andriin@fb.com>
> > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > ---
> > .../selftests/bpf/prog_tests/bpf_obj_id.c | 2 +-
> > .../bpf/prog_tests/bpf_verif_scale.c | 10 +---
> > .../selftests/bpf/prog_tests/flow_dissector.c | 2 +-
> > .../bpf/prog_tests/get_stack_raw_tp.c | 2 +-
> > .../selftests/bpf/prog_tests/global_data.c | 10 ++--
> > .../selftests/bpf/prog_tests/l4lb_all.c | 4 +-
> > .../selftests/bpf/prog_tests/map_lock.c | 8 +--
> > .../selftests/bpf/prog_tests/pkt_access.c | 2 +-
> > .../selftests/bpf/prog_tests/pkt_md_access.c | 2 +-
> > .../bpf/prog_tests/queue_stack_map.c | 4 +-
> > .../bpf/prog_tests/reference_tracking.c | 2 +-
> > .../selftests/bpf/prog_tests/spinlock.c | 2 +-
> > .../selftests/bpf/prog_tests/stacktrace_map.c | 2 +-
> > .../bpf/prog_tests/stacktrace_map_raw_tp.c | 2 +-
> > .../bpf/prog_tests/task_fd_query_rawtp.c | 2 +-
> > .../bpf/prog_tests/task_fd_query_tp.c | 2 +-
> > .../selftests/bpf/prog_tests/tcp_estats.c | 2 +-
> > tools/testing/selftests/bpf/prog_tests/xdp.c | 2 +-
> > .../bpf/prog_tests/xdp_adjust_tail.c | 2 +-
> > .../selftests/bpf/prog_tests/xdp_noinline.c | 4 +-
> > tools/testing/selftests/bpf/test_progs.c | 55 ++++++++-----------
> > tools/testing/selftests/bpf/test_progs.h | 26 +++++++--
> > 22 files changed, 75 insertions(+), 74 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c b/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
> > index fb5840a62548..f57e0c625de3 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/bpf_obj_id.c
> > @@ -49,7 +49,7 @@ void test_bpf_obj_id(void)
> > * to load.
> > */
> > if (err)
> > - error_cnt++;
> > + test__fail();
> > assert(!err);
> >
> > /* Insert a magic value to the map */
> > diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
> > index 1a1eae356f81..217988243077 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
> > @@ -28,8 +28,6 @@ static int check_load(const char *file, enum bpf_prog_type type)
> > attr.prog_flags = BPF_F_TEST_RND_HI32;
> > err = bpf_prog_load_xattr(&attr, &obj, &prog_fd);
> > bpf_object__close(obj);
> > - if (err)
> > - error_cnt++;
> > return err;
> > }
> >
> > @@ -105,12 +103,8 @@ void test_bpf_verif_scale(void)
> > continue;
> >
> > err = check_load(test->file, test->attach_type);
> > - if (test->fails) { /* expected to fail */
> > - if (err)
> > - error_cnt--;
> > - else
> > - error_cnt++;
> > - }
> > + if (err && !test->fails)
> > + test__fail();
> > }
> >
> > if (env.verifier_stats)
> > diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
> > index 6892b88ae065..e9d882c05ded 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
> > @@ -453,7 +453,7 @@ void test_flow_dissector(void)
> > err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
> > "jmp_table", "last_dissection", &prog_fd, &keys_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
> > index 3d59b3c841fe..afc60f62e2a8 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
> > @@ -137,7 +137,7 @@ void test_get_stack_raw_tp(void)
> >
> > goto close_prog_noerr;
> > close_prog:
> > - error_cnt++;
> > + test__fail();
> > close_prog_noerr:
> > if (!IS_ERR_OR_NULL(link))
> > bpf_link__destroy(link);
> > diff --git a/tools/testing/selftests/bpf/prog_tests/global_data.c b/tools/testing/selftests/bpf/prog_tests/global_data.c
> > index d011079fb0bf..db13bfee6bb9 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/global_data.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/global_data.c
> > @@ -8,7 +8,7 @@ static void test_global_data_number(struct bpf_object *obj, __u32 duration)
> >
> > map_fd = bpf_find_map(__func__, obj, "result_number");
> > if (map_fd < 0) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > @@ -45,7 +45,7 @@ static void test_global_data_string(struct bpf_object *obj, __u32 duration)
> >
> > map_fd = bpf_find_map(__func__, obj, "result_string");
> > if (map_fd < 0) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > @@ -82,7 +82,7 @@ static void test_global_data_struct(struct bpf_object *obj, __u32 duration)
> >
> > map_fd = bpf_find_map(__func__, obj, "result_struct");
> > if (map_fd < 0) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > @@ -113,13 +113,13 @@ static void test_global_data_rdonly(struct bpf_object *obj, __u32 duration)
> >
> > map = bpf_object__find_map_by_name(obj, "test_glo.rodata");
> > if (!map || !bpf_map__is_internal(map)) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > map_fd = bpf_map__fd(map);
> > if (map_fd < 0) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c
> > index 20ddca830e68..724bb40de1f8 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/l4lb_all.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/l4lb_all.c
> > @@ -31,7 +31,7 @@ static void test_l4lb(const char *file)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > @@ -73,7 +73,7 @@ static void test_l4lb(const char *file)
> > pkts += stats[i].pkts;
> > }
> > if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
> > - error_cnt++;
> > + test__fail();
> > printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
> > }
> > out:
> > diff --git a/tools/testing/selftests/bpf/prog_tests/map_lock.c b/tools/testing/selftests/bpf/prog_tests/map_lock.c
> > index ee99368c595c..12123ff1f31f 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/map_lock.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/map_lock.c
> > @@ -10,12 +10,12 @@ static void *parallel_map_access(void *arg)
> > err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK);
> > if (err) {
> > printf("lookup failed\n");
> > - error_cnt++;
> > + test__fail();
> > goto out;
> > }
> > if (vars[0] != 0) {
> > printf("lookup #%d var[0]=%d\n", i, vars[0]);
> > - error_cnt++;
> > + test__fail();
> > goto out;
> > }
> > rnd = vars[1];
> > @@ -24,7 +24,7 @@ static void *parallel_map_access(void *arg)
> > continue;
> > printf("lookup #%d var[1]=%d var[%d]=%d\n",
> > i, rnd, j, vars[j]);
> > - error_cnt++;
> > + test__fail();
> > goto out;
> > }
> > }
> > @@ -69,7 +69,7 @@ void test_map_lock(void)
> > ret == (void *)&map_fd[i - 4]);
> > goto close_prog_noerr;
> > close_prog:
> > - error_cnt++;
> > + test__fail();
> > close_prog_noerr:
> > bpf_object__close(obj);
> > }
> > diff --git a/tools/testing/selftests/bpf/prog_tests/pkt_access.c b/tools/testing/selftests/bpf/prog_tests/pkt_access.c
> > index 4ecfd721a044..9ef4e4ffb379 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/pkt_access.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/pkt_access.c
> > @@ -10,7 +10,7 @@ void test_pkt_access(void)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c b/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c
> > index ac0d43435806..c354b9d21f4f 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/pkt_md_access.c
> > @@ -10,7 +10,7 @@ void test_pkt_md_access(void)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c b/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
> > index e60cd5ff1f55..48a8cd144bd1 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/queue_stack_map.c
> > @@ -28,7 +28,7 @@ static void test_queue_stack_map_by_type(int type)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > @@ -44,7 +44,7 @@ static void test_queue_stack_map_by_type(int type)
> > for (i = 0; i < MAP_SIZE; i++) {
> > err = bpf_map_update_elem(map_in_fd, NULL, &vals[i], 0);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > goto out;
> > }
> > }
> > diff --git a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c
> > index 4a4f428d1a78..f6987e3dd28c 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c
> > @@ -11,7 +11,7 @@ void test_reference_tracking(void)
> >
> > obj = bpf_object__open(file);
> > if (IS_ERR(obj)) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/spinlock.c b/tools/testing/selftests/bpf/prog_tests/spinlock.c
> > index 114ebe6a438e..e843336713e8 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/spinlock.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/spinlock.c
> > @@ -23,7 +23,7 @@ void test_spinlock(void)
> > ret == (void *)&prog_fd);
> > goto close_prog_noerr;
> > close_prog:
> > - error_cnt++;
> > + test__fail();
> > close_prog_noerr:
> > bpf_object__close(obj);
> > }
> > diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
> > index fc539335c5b3..9dba1cc3da60 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
> > @@ -70,7 +70,7 @@ void test_stacktrace_map(void)
> >
> > goto disable_pmu_noerr;
> > disable_pmu:
> > - error_cnt++;
> > + test__fail();
> > disable_pmu_noerr:
> > bpf_link__destroy(link);
> > close_prog:
> > diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c
> > index fbfa8e76cf63..4e7cf2e663f7 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_map_raw_tp.c
> > @@ -60,7 +60,7 @@ void test_stacktrace_map_raw_tp(void)
> >
> > goto close_prog_noerr;
> > close_prog:
> > - error_cnt++;
> > + test__fail();
> > close_prog_noerr:
> > if (!IS_ERR_OR_NULL(link))
> > bpf_link__destroy(link);
> > diff --git a/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c b/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c
> > index 958a3d88de99..d9ad1aa8a026 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c
> > @@ -72,7 +72,7 @@ void test_task_fd_query_rawtp(void)
> >
> > goto close_prog_noerr;
> > close_prog:
> > - error_cnt++;
> > + test__fail();
> > close_prog_noerr:
> > bpf_object__close(obj);
> > }
> > diff --git a/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c b/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c
> > index f9b70e81682b..76209f2386c8 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c
> > @@ -68,7 +68,7 @@ static void test_task_fd_query_tp_core(const char *probe_name,
> > close_pmu:
> > close(pmu_fd);
> > close_prog:
> > - error_cnt++;
> > + test__fail();
> > close_prog_noerr:
> > bpf_object__close(obj);
> > }
> > diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_estats.c b/tools/testing/selftests/bpf/prog_tests/tcp_estats.c
> > index bb8759d69099..e241e5d7c71f 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/tcp_estats.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/tcp_estats.c
> > @@ -11,7 +11,7 @@ void test_tcp_estats(void)
> > err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
> > CHECK(err, "", "err %d errno %d\n", err, errno);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/xdp.c b/tools/testing/selftests/bpf/prog_tests/xdp.c
> > index a74167289545..7c9f89fa1d02 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/xdp.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/xdp.c
> > @@ -17,7 +17,7 @@ void test_xdp(void)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
> > index 922aa0a19764..a479a3303c3b 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
> > @@ -11,7 +11,7 @@ void test_xdp_adjust_tail(void)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c
> > index 15f7c272edb0..10bef9d5ab81 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/xdp_noinline.c
> > @@ -32,7 +32,7 @@ void test_xdp_noinline(void)
> >
> > err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
> > if (err) {
> > - error_cnt++;
> > + test__fail();
> > return;
> > }
> >
> > @@ -74,7 +74,7 @@ void test_xdp_noinline(void)
> > pkts += stats[i].pkts;
> > }
> > if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
> > - error_cnt++;
> > + test__fail();
> > printf("test_xdp_noinline:FAIL:stats %lld %lld\n",
> > bytes, pkts);
> > }
> > diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> > index 1993f2ce0d23..ad90e45768ce 100644
> > --- a/tools/testing/selftests/bpf/test_progs.c
> > +++ b/tools/testing/selftests/bpf/test_progs.c
> > @@ -8,24 +8,6 @@
> >
> > /* defined in test_progs.h */
> > struct test_env env;
> > -int error_cnt, pass_cnt;
> > -
> > -struct prog_test_def {
> > - const char *test_name;
> > - int test_num;
> > - void (*run_test)(void);
> > - bool force_log;
> > - int pass_cnt;
> > - int error_cnt;
> > - bool tested;
> > -
> > - const char *subtest_name;
> > - int subtest_num;
> > -
> > - /* store counts before subtest started */
> > - int old_pass_cnt;
> > - int old_error_cnt;
> > -};
> >
> > static bool should_run(struct test_selector *sel, int num, const char *name)
> > {
> > @@ -74,14 +56,14 @@ static const char *test_status_string(bool success)
> > void test__end_subtest()
> > {
> > struct prog_test_def *test = env.test;
> > - int sub_error_cnt = error_cnt - test->old_error_cnt;
> > + int sub_fail_cnt = test->fail_cnt - test->old_fail_cnt;
> >
> > - if (sub_error_cnt)
> > - env.fail_cnt++;
> > + if (sub_fail_cnt)
> > + test->fail_cnt++;
> > else
> > env.sub_succ_cnt++;
> >
> > - dump_test_log(test, sub_error_cnt);
> > + dump_test_log(test, sub_fail_cnt);
> >
> > fprintf(env.stdout, "#%3d/%-3d %4s %s:%s\n",
> > test->test_num, test->subtest_num,
> > @@ -111,8 +93,8 @@ bool test__start_subtest(const char *name)
> > return false;
> >
> > test->subtest_name = name;
> > - env.test->old_pass_cnt = pass_cnt;
> > - env.test->old_error_cnt = error_cnt;
> > + env.test->old_succ_cnt = env.test->succ_cnt;
> > + env.test->old_fail_cnt = env.test->fail_cnt;
> >
> > return true;
> > }
> > @@ -126,6 +108,19 @@ void test__skip(void)
> > env.skip_cnt++;
> > }
> >
> > +void __test__fail(const char *file, int line)
> > +{
> > + if (env.test->subtest_name)
> > + fprintf(stderr, "%s:%s failed at %s:%d, errno=%d\n",
>
> Nit: let's keep <test>/<subtest> convention here as well?
>
> Failure doesn't always set errno, this will be quite confusing
> sometimes. Especially for higher-level libbpf APIs, which don't set
> errno at all.
> If test wants to log additional information, let it do it explicitly.
SG. Maybe we can adapt log_err from cgroup_helpers.h for error reporting
once I move sockopt tests into test_progs.
> Also, _CHECK already logs error message, so this is going to be
> double-verbose for typical case. I'd say let's drop these error
> messages and instead slightly extend _CHECK one with line number (it
> already logs func name).
Not everything goes through the _CHECK macro unfortunately, see
all the cases where I did s/error_cnt++/test__fail/. How about I
remove the error message from _CHECK and leave it in __test_fail?
> > + env.test->test_name, env.test->subtest_name,
> > + file, line, errno);
> > + else
> > + fprintf(stderr, "%s failed at %s:%d, errno=%d\n",
> > + env.test->test_name, file, line, errno);
> > +
> > + env.test->fail_cnt++;
> > +}
> > +
> > struct ipv4_packet pkt_v4 = {
> > .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> > .iph.ihl = 5,
> > @@ -150,7 +145,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
> > map = bpf_object__find_map_by_name(obj, name);
> > if (!map) {
> > printf("%s:FAIL:map '%s' not found\n", test, name);
> > - error_cnt++;
> > + test__fail();
> > return -1;
> > }
> > return bpf_map__fd(map);
> > @@ -509,8 +504,6 @@ int main(int argc, char **argv)
> > stdio_hijack();
> > for (i = 0; i < prog_test_cnt; i++) {
> > struct prog_test_def *test = &prog_test_defs[i];
> > - int old_pass_cnt = pass_cnt;
> > - int old_error_cnt = error_cnt;
> >
> > env.test = test;
> > test->test_num = i + 1;
> > @@ -525,14 +518,12 @@ int main(int argc, char **argv)
> > test__end_subtest();
> >
> > test->tested = true;
> > - test->pass_cnt = pass_cnt - old_pass_cnt;
> > - test->error_cnt = error_cnt - old_error_cnt;
> > - if (test->error_cnt)
> > + if (test->fail_cnt)
> > env.fail_cnt++;
> > else
> > env.succ_cnt++;
> >
> > - dump_test_log(test, test->error_cnt);
> > + dump_test_log(test, test->fail_cnt);
> >
> > fprintf(env.stdout, "#%3d %4s %s\n",
> > test->test_num,
> > @@ -546,5 +537,5 @@ int main(int argc, char **argv)
> > free(env.test_selector.num_set);
> > free(env.subtest_selector.num_set);
> >
> > - return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> > + return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> > }
> > diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> > index 9defd35cb6c0..7b05921784a4 100644
> > --- a/tools/testing/selftests/bpf/test_progs.h
> > +++ b/tools/testing/selftests/bpf/test_progs.h
> > @@ -38,7 +38,23 @@ typedef __u16 __sum16;
> > #include "trace_helpers.h"
> > #include "flow_dissector_load.h"
> >
> > -struct prog_test_def;
> > +struct prog_test_def {
> > + const char *test_name;
> > + int test_num;
> > + void (*run_test)(void);
> > + bool force_log;
> > + bool tested;
> > +
> > + const char *subtest_name;
> > + int subtest_num;
> > +
> > + int succ_cnt;
> > + int fail_cnt;
>
> So I'm neutral on this rename, I even considered it myself initially.
> But keep in mind, that succ/fail in env means number of tests, while
> test->succ/fail means number of assertions. We don't report total
> number of failed checks anymore, so it doesn't matter, but if we ever
> want to keep track of that at env level, it will be very confusing and
> inconvenient.
Point taken, I didn't think about it, let me undo the rename. I'll
try to add a comment instead to highlight the difference.
> > +
> > + /* store counts before subtest started */
> > + int old_succ_cnt;
> > + int old_fail_cnt;
> > +};
>
> Did you move it here just to access env.test->succ_cnt in _CHECK()?
> Maybe add test__success() counterpart to test__fail() instead?
Yeah, good point, will do.
> >
> > struct test_selector {
> > const char *name;
> > @@ -67,13 +83,13 @@ struct test_env {
> > int skip_cnt; /* skipped tests */
> > };
> >
> > -extern int error_cnt;
> > -extern int pass_cnt;
> > extern struct test_env env;
> >
> > extern void test__force_log();
> > extern bool test__start_subtest(const char *name);
> > extern void test__skip(void);
> > +#define test__fail() __test__fail(__FILE__, __LINE__)
> > +extern void __test__fail(const char *file, int line);
>
> Given my comment above about too verbose logging, I'd say let's keep
> this simple and have just
>
> extern void test__fail()
>
> And let _CHECK log file:line.
See above about test__fail without _CHECK. Maybe we should do QCHECK
as you suggested in the other email.
So those lonely:
if (err) {
error_cnt++;
return;
}
checks can instead be converted to:
if (QCHECK(err))
return;
Let me play with it a bit and see how it goes.
> >
> > #define MAGIC_BYTES 123
> >
> > @@ -96,11 +112,11 @@ extern struct ipv6_packet pkt_v6;
> > #define _CHECK(condition, tag, duration, format...) ({ \
> > int __ret = !!(condition); \
> > if (__ret) { \
> > - error_cnt++; \
> > + test__fail(); \
> > printf("%s:FAIL:%s ", __func__, tag); \
> > printf(format); \
> > } else { \
> > - pass_cnt++; \
> > + env.test->succ_cnt++; \
> > printf("%s:PASS:%s %d nsec\n", \
> > __func__, tag, duration); \
> > } \
> > --
> > 2.23.0.rc1.153.gdeed80330f-goog
> >
^ permalink raw reply
* Re: [PATCH net-next] mcast: ensure L-L IPv6 packets are accepted by bridge
From: Linus Lüssing @ 2019-08-14 20:11 UTC (permalink / raw)
To: Patrick Ruddy; +Cc: bridge, Nikolay Aleksandrov, Ido Schimmel, netdev, roopa
In-Reply-To: <620d3cfbe58e3ae87ef1d5e7f2aa1588cac3e64a.camel@vyatta.att-mail.com>
On Wed, Aug 14, 2019 at 05:40:58PM +0100, Patrick Ruddy wrote:
> The group is being joined by MLD at the L3 level but the packets are
> not being passed up to the l3 interface becasue there is a MLD querier
> on the network
>
> snippet from /proc/net/igmp6
> ...
> 40 sw1 ff0200000000000000000001ff008700 1 00000004 0
> 40 sw1 ff020000000000000000000000000002 1 00000004 0
> 40 sw1 ff020000000000000000000000000001 1 0000000C 0
> 40 sw1 ff010000000000000000000000000001 1 00000008 0
> 41 lo1 ff020000000000000000000000000001 1 0000000C 0
> 41 lo1 ff010000000000000000000000000001 1 00000008 0
> 42 sw1.1 ff020000000000000000000000000006 1 00000004 0
> 42 sw1.1 ff020000000000000000000000000005 1 00000004 0
> 42 sw1.1 ff0200000000000000000001ff000000 2 00000004 0
> 42 sw1.1 ff0200000000000000000001ff008700 1 00000004 0
> 42 sw1.1 ff0200000000000000000001ff000099 1 00000004 0
> 42 sw1.1 ff020000000000000000000000000002 1 00000004 0
> 42 sw1.1 ff020000000000000000000000000001 1 0000000C 0
> 42 sw1.1 ff010000000000000000000000000001 1 00000008 0
> ...
>
> the bridge is sw1 and the l3 intervace is sw1.1
What kind of interface is sw1.1 exactly? Is it a VLAN or a VRF
interface? Something else?
Could you also post the output of bridge mdb show?
Regards, Linus
PS: Also please include the bridge mailinglist in the future.
^ permalink raw reply
* [PATCH] hv_netvsc: Fix a memory leak bug
From: Wenwen Wang @ 2019-08-14 20:16 UTC (permalink / raw)
To: Wenwen Wang
Cc: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Sasha Levin,
David S. Miller, open list:Hyper-V CORE AND DRIVERS,
open list:NETWORKING DRIVERS, open list
In rndis_filter_device_add(), 'rndis_device' is allocated through kzalloc()
by invoking get_rndis_device(). In the following execution, if an error
occurs, the execution will go to the 'err_dev_remv' label. However, the
allocated 'rndis_device' is not deallocated, leading to a memory leak bug.
Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
---
drivers/net/hyperv/rndis_filter.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 317dbe9..ed35085 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1420,6 +1420,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
err_dev_remv:
rndis_filter_device_remove(dev, net_device);
+ kfree(rndis_device);
return ERR_PTR(ret);
}
--
2.7.4
^ permalink raw reply related
* Re: [RFC bpf-next 0/3] tools: bpftool: add subcommand to count map entries
From: Andrii Nakryiko @ 2019-08-14 20:18 UTC (permalink / raw)
To: Quentin Monnet
Cc: Alexei Starovoitov, Edward Cree, Alexei Starovoitov,
Daniel Borkmann, bpf, Network Development, oss-drivers
In-Reply-To: <bec14521-dec1-5e1b-2f29-5c0492500272@netronome.com>
On Wed, Aug 14, 2019 at 10:12 AM Quentin Monnet
<quentin.monnet@netronome.com> wrote:
>
> 2019-08-14 09:58 UTC-0700 ~ Alexei Starovoitov
> <alexei.starovoitov@gmail.com>
> > On Wed, Aug 14, 2019 at 9:45 AM Edward Cree <ecree@solarflare.com> wrote:
> >>
> >> On 14/08/2019 10:42, Quentin Monnet wrote:
> >>> 2019-08-13 18:51 UTC-0700 ~ Alexei Starovoitov
> >>> <alexei.starovoitov@gmail.com>
> >>>> The same can be achieved by 'bpftool map dump|grep key|wc -l', no?
> >>> To some extent (with subtleties for some other map types); and we use a
> >>> similar command line as a workaround for now. But because of the rate of
> >>> inserts/deletes in the map, the process often reports a number higher
> >>> than the max number of entries (we observed up to ~750k when max_entries
> >>> is 500k), even is the map is only half-full on average during the count.
> >>> On the worst case (though not frequent), an entry is deleted just before
> >>> we get the next key from it, and iteration starts all over again. This
> >>> is not reliable to determine how much space is left in the map.
> >>>
> >>> I cannot see a solution that would provide a more accurate count from
> >>> user space, when the map is under pressure?
> >> This might be a really dumb suggestion, but: you're wanting to collect a
> >> summary statistic over an in-kernel data structure in a single syscall,
> >> because making a series of syscalls to examine every entry is slow and
> >> racy. Isn't that exactly a job for an in-kernel virtual machine, and
> >> could you not supply an eBPF program which the kernel runs on each entry
> >> in the map, thus supporting people who want to calculate something else
> >> (mean, min and max, whatever) instead of count?
> >
> > Pretty much my suggestion as well :)
I also support the suggestion to count it from BPF side. It's flexible
and powerful approach and doesn't require adding more and more nuanced
sub-APIs to kernel to support subset of bulk operations on map
(subset, because we'll expose count, but what about, e.g., p50, etc,
there will always be something more that someone will want and it just
doesn't scale).
> >
> > It seems the better fix for your nat threshold is to keep count of
> > elements in the map in a separate global variable that
> > bpf program manually increments and decrements.
> > bpftool will dump it just as regular map of single element.
> > (I believe it doesn't recognize global variables properly yet)
> > and BTF will be there to pick exactly that 'count' variable.
> >
>
> It would be with an offloaded map, but yes, I suppose we could keep
> track of the numbers in a separate map. We'll have a look into this.
See if you can use a global variable, that way you completely
eliminate any overhead from BPF side of things, except for atomic
increment.
>
> Thanks to both of you for the suggestions.
> Quentin
^ permalink raw reply
* Re: [PATCH bpf-next 3/4] selftests/bpf: test_progs: remove global fail/success counts
From: Andrii Nakryiko @ 2019-08-14 20:22 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Stanislav Fomichev, Networking, bpf, David S. Miller,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
In-Reply-To: <20190814200751.GM2820@mini-arch>
On Wed, Aug 14, 2019 at 1:07 PM Stanislav Fomichev <sdf@fomichev.me> wrote:
>
> On 08/14, Andrii Nakryiko wrote:
> > On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@google.com> wrote:
> > >
> > > Now that we have a global per-test/per-environment state, there
> > > is no longer the need to have global fail/success counters
> > > (and there is no need to save/get the diff before/after the
> > > test).
> > >
> > > Cc: Andrii Nakryiko <andriin@fb.com>
> > > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > > ---
[...]
> > > +void __test__fail(const char *file, int line)
> > > +{
> > > + if (env.test->subtest_name)
> > > + fprintf(stderr, "%s:%s failed at %s:%d, errno=%d\n",
> >
> > Nit: let's keep <test>/<subtest> convention here as well?
> >
> > Failure doesn't always set errno, this will be quite confusing
> > sometimes. Especially for higher-level libbpf APIs, which don't set
> > errno at all.
> > If test wants to log additional information, let it do it explicitly.
> SG. Maybe we can adapt log_err from cgroup_helpers.h for error reporting
> once I move sockopt tests into test_progs.
>
> > Also, _CHECK already logs error message, so this is going to be
> > double-verbose for typical case. I'd say let's drop these error
> > messages and instead slightly extend _CHECK one with line number (it
> > already logs func name).
> Not everything goes through the _CHECK macro unfortunately, see
Well, it should (at least eventually). If existing macro doesn't cover
typical use case, we can add one that does cover.
> all the cases where I did s/error_cnt++/test__fail/. How about I
> remove the error message from _CHECK and leave it in __test_fail?
I'd keep test__fail() and test__success() as a low-level building
block. And move all the logging into corresponding high-level macro.
This still gives flexibility to do one-off crazy tests, if necessary,
while having consistent approach for everything else.
>
> > > + env.test->test_name, env.test->subtest_name,
> > > + file, line, errno);
> > > + else
> > > + fprintf(stderr, "%s failed at %s:%d, errno=%d\n",
> > > + env.test->test_name, file, line, errno);
> > > +
> > > + env.test->fail_cnt++;
> > > +}
> > > +
> > > struct ipv4_packet pkt_v4 = {
> > > .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
> > > .iph.ihl = 5,
> > > @@ -150,7 +145,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
> > > map = bpf_object__find_map_by_name(obj, name);
> > > if (!map) {
> > > printf("%s:FAIL:map '%s' not found\n", test, name);
> > > - error_cnt++;
> > > + test__fail();
> > > return -1;
> > > }
> > > return bpf_map__fd(map);
> > > @@ -509,8 +504,6 @@ int main(int argc, char **argv)
> > > stdio_hijack();
> > > for (i = 0; i < prog_test_cnt; i++) {
> > > struct prog_test_def *test = &prog_test_defs[i];
> > > - int old_pass_cnt = pass_cnt;
> > > - int old_error_cnt = error_cnt;
> > >
> > > env.test = test;
> > > test->test_num = i + 1;
> > > @@ -525,14 +518,12 @@ int main(int argc, char **argv)
> > > test__end_subtest();
> > >
> > > test->tested = true;
> > > - test->pass_cnt = pass_cnt - old_pass_cnt;
> > > - test->error_cnt = error_cnt - old_error_cnt;
> > > - if (test->error_cnt)
> > > + if (test->fail_cnt)
> > > env.fail_cnt++;
> > > else
> > > env.succ_cnt++;
> > >
> > > - dump_test_log(test, test->error_cnt);
> > > + dump_test_log(test, test->fail_cnt);
> > >
> > > fprintf(env.stdout, "#%3d %4s %s\n",
> > > test->test_num,
> > > @@ -546,5 +537,5 @@ int main(int argc, char **argv)
> > > free(env.test_selector.num_set);
> > > free(env.subtest_selector.num_set);
> > >
> > > - return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> > > + return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> > > }
> > > diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
> > > index 9defd35cb6c0..7b05921784a4 100644
> > > --- a/tools/testing/selftests/bpf/test_progs.h
> > > +++ b/tools/testing/selftests/bpf/test_progs.h
> > > @@ -38,7 +38,23 @@ typedef __u16 __sum16;
> > > #include "trace_helpers.h"
> > > #include "flow_dissector_load.h"
> > >
> > > -struct prog_test_def;
> > > +struct prog_test_def {
> > > + const char *test_name;
> > > + int test_num;
> > > + void (*run_test)(void);
> > > + bool force_log;
> > > + bool tested;
> > > +
> > > + const char *subtest_name;
> > > + int subtest_num;
> > > +
> > > + int succ_cnt;
> > > + int fail_cnt;
> >
> > So I'm neutral on this rename, I even considered it myself initially.
> > But keep in mind, that succ/fail in env means number of tests, while
> > test->succ/fail means number of assertions. We don't report total
> > number of failed checks anymore, so it doesn't matter, but if we ever
> > want to keep track of that at env level, it will be very confusing and
> > inconvenient.
> Point taken, I didn't think about it, let me undo the rename. I'll
> try to add a comment instead to highlight the difference.
>
> > > +
> > > + /* store counts before subtest started */
> > > + int old_succ_cnt;
> > > + int old_fail_cnt;
> > > +};
> >
> > Did you move it here just to access env.test->succ_cnt in _CHECK()?
> > Maybe add test__success() counterpart to test__fail() instead?
> Yeah, good point, will do.
>
> > >
> > > struct test_selector {
> > > const char *name;
> > > @@ -67,13 +83,13 @@ struct test_env {
> > > int skip_cnt; /* skipped tests */
> > > };
> > >
> > > -extern int error_cnt;
> > > -extern int pass_cnt;
> > > extern struct test_env env;
> > >
> > > extern void test__force_log();
> > > extern bool test__start_subtest(const char *name);
> > > extern void test__skip(void);
> > > +#define test__fail() __test__fail(__FILE__, __LINE__)
> > > +extern void __test__fail(const char *file, int line);
> >
> > Given my comment above about too verbose logging, I'd say let's keep
> > this simple and have just
> >
> > extern void test__fail()
> >
> > And let _CHECK log file:line.
> See above about test__fail without _CHECK. Maybe we should do QCHECK
> as you suggested in the other email.
>
> So those lonely:
>
> if (err) {
> error_cnt++;
> return;
> }
>
> checks can instead be converted to:
>
> if (QCHECK(err))
> return;
>
> Let me play with it a bit and see how it goes.
Yeah, give it a go. Try keeping file:line logging in macro, where it's
more natural, IMO.
>
> > >
> > > #define MAGIC_BYTES 123
> > >
> > > @@ -96,11 +112,11 @@ extern struct ipv6_packet pkt_v6;
> > > #define _CHECK(condition, tag, duration, format...) ({ \
> > > int __ret = !!(condition); \
> > > if (__ret) { \
> > > - error_cnt++; \
> > > + test__fail(); \
> > > printf("%s:FAIL:%s ", __func__, tag); \
> > > printf(format); \
> > > } else { \
> > > - pass_cnt++; \
> > > + env.test->succ_cnt++; \
> > > printf("%s:PASS:%s %d nsec\n", \
> > > __func__, tag, duration); \
> > > } \
> > > --
> > > 2.23.0.rc1.153.gdeed80330f-goog
> > >
^ permalink raw reply
* Re: [PATCH net-next] mcast: ensure L-L IPv6 packets are accepted by bridge
From: Nikolay Aleksandrov @ 2019-08-14 20:34 UTC (permalink / raw)
To: Linus Lüssing, Patrick Ruddy; +Cc: bridge, Ido Schimmel, netdev, roopa
In-Reply-To: <20190814201138.GE2431@otheros>
On 8/14/19 11:11 PM, Linus Lüssing wrote:
> On Wed, Aug 14, 2019 at 05:40:58PM +0100, Patrick Ruddy wrote:
>> The group is being joined by MLD at the L3 level but the packets are
>> not being passed up to the l3 interface becasue there is a MLD querier
>> on the network
>>
>> snippet from /proc/net/igmp6
>> ...
>> 40 sw1 ff0200000000000000000001ff008700 1 00000004 0
>> 40 sw1 ff020000000000000000000000000002 1 00000004 0
>> 40 sw1 ff020000000000000000000000000001 1 0000000C 0
>> 40 sw1 ff010000000000000000000000000001 1 00000008 0
>> 41 lo1 ff020000000000000000000000000001 1 0000000C 0
>> 41 lo1 ff010000000000000000000000000001 1 00000008 0
>> 42 sw1.1 ff020000000000000000000000000006 1 00000004 0
>> 42 sw1.1 ff020000000000000000000000000005 1 00000004 0
>> 42 sw1.1 ff0200000000000000000001ff000000 2 00000004 0
>> 42 sw1.1 ff0200000000000000000001ff008700 1 00000004 0
>> 42 sw1.1 ff0200000000000000000001ff000099 1 00000004 0
>> 42 sw1.1 ff020000000000000000000000000002 1 00000004 0
>> 42 sw1.1 ff020000000000000000000000000001 1 0000000C 0
>> 42 sw1.1 ff010000000000000000000000000001 1 00000008 0
>> ...
>>
>> the bridge is sw1 and the l3 intervace is sw1.1
>
> What kind of interface is sw1.1 exactly? Is it a VLAN or a VRF
> interface? Something else?
>
+1
> Could you also post the output of bridge mdb show?
>
> Regards, Linus
>
>
> PS: Also please include the bridge mailinglist in the future.
>
Note that if you'd like to debug a host joined group currently bridge mdb show
will not dump it and if the group is host-joined only it
can even be empty. You can use my latest set (not applied yet):
http://patchwork.ozlabs.org/project/netdev/list/?series=125169
Alternatively you could monitor the mdb events, it will show up there even
today without any changes (bridge monitor mdb) and you can check if it's
getting deleted.
Cheers,
Nik
^ permalink raw reply
* RE: [PATCH] hv_netvsc: Fix a memory leak bug
From: Haiyang Zhang @ 2019-08-14 20:35 UTC (permalink / raw)
To: Wenwen Wang
Cc: KY Srinivasan, Stephen Hemminger, Sasha Levin, David S. Miller,
open list:Hyper-V CORE AND DRIVERS, open list:NETWORKING DRIVERS,
open list
In-Reply-To: <1565813771-8967-1-git-send-email-wenwen@cs.uga.edu>
> -----Original Message-----
> From: Wenwen Wang <wenwen@cs.uga.edu>
> Sent: Wednesday, August 14, 2019 4:16 PM
> To: Wenwen Wang <wenwen@cs.uga.edu>
> Cc: KY Srinivasan <kys@microsoft.com>; Haiyang Zhang
> <haiyangz@microsoft.com>; Stephen Hemminger
> <sthemmin@microsoft.com>; Sasha Levin <sashal@kernel.org>; David S.
> Miller <davem@davemloft.net>; open list:Hyper-V CORE AND DRIVERS
> <linux-hyperv@vger.kernel.org>; open list:NETWORKING DRIVERS
> <netdev@vger.kernel.org>; open list <linux-kernel@vger.kernel.org>
> Subject: [PATCH] hv_netvsc: Fix a memory leak bug
>
> In rndis_filter_device_add(), 'rndis_device' is allocated through kzalloc()
> by invoking get_rndis_device(). In the following execution, if an error
> occurs, the execution will go to the 'err_dev_remv' label. However, the
> allocated 'rndis_device' is not deallocated, leading to a memory leak bug.
>
> Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
> ---
> drivers/net/hyperv/rndis_filter.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/hyperv/rndis_filter.c
> b/drivers/net/hyperv/rndis_filter.c
> index 317dbe9..ed35085 100644
> --- a/drivers/net/hyperv/rndis_filter.c
> +++ b/drivers/net/hyperv/rndis_filter.c
> @@ -1420,6 +1420,7 @@ struct netvsc_device
> *rndis_filter_device_add(struct hv_device *dev,
>
> err_dev_remv:
> rndis_filter_device_remove(dev, net_device);
> + kfree(rndis_device);
The kfree() is not necessary here.
Because it is already freed by --
rndis_filter_device_remove() --> netvsc_device_remove()
--> free_netvsc_device_rcu() --> free_netvsc_device()
--> kfree(nvdev->extension); //This frees rndis_device.
Thanks,
- Haiyang
^ permalink raw reply
* Re: [PATCH] hv_netvsc: Fix a memory leak bug
From: Stephen Hemminger @ 2019-08-14 20:37 UTC (permalink / raw)
To: Wenwen Wang
Cc: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Sasha Levin,
David S. Miller, open list:Hyper-V CORE AND DRIVERS,
open list:NETWORKING DRIVERS, open list
In-Reply-To: <1565813771-8967-1-git-send-email-wenwen@cs.uga.edu>
On Wed, 14 Aug 2019 15:16:11 -0500
Wenwen Wang <wenwen@cs.uga.edu> wrote:
> In rndis_filter_device_add(), 'rndis_device' is allocated through kzalloc()
> by invoking get_rndis_device(). In the following execution, if an error
> occurs, the execution will go to the 'err_dev_remv' label. However, the
> allocated 'rndis_device' is not deallocated, leading to a memory leak bug.
>
> Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
> ---
> drivers/net/hyperv/rndis_filter.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
> index 317dbe9..ed35085 100644
> --- a/drivers/net/hyperv/rndis_filter.c
> +++ b/drivers/net/hyperv/rndis_filter.c
> @@ -1420,6 +1420,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
>
> err_dev_remv:
> rndis_filter_device_remove(dev, net_device);
> + kfree(rndis_device);
> return ERR_PTR(ret);
> }
>
The rndis_device is already freed by:
rndis_filter_device_remove
netvsc_device_remove
free_netvsc_device_rcu
free_netvsc_device called by rcu
static void free_netvsc_device(struct rcu_head *head)
{
struct netvsc_device *nvdev
= container_of(head, struct netvsc_device, rcu);
int i;
kfree(nvdev->extension); << here
^ permalink raw reply
* Re: [PATCH net-next, 3/6] net/mlx5: Add wrappers for HyperV PCIe operations
From: Mark Bloch @ 2019-08-14 20:41 UTC (permalink / raw)
To: haiyangz, sashal@kernel.org, davem@davemloft.net, Saeed Mahameed,
leon@kernel.org, Eran Ben Elisha, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: kys, Stephen Hemminger, linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-4-git-send-email-haiyangz@microsoft.com>
On 8/14/19 12:08 PM, Haiyang Zhang wrote:
> From: Eran Ben Elisha <eranbe@mellanox.com>
>
> Add wrapper functions for HyperV PCIe read / write /
> block_invalidate_register operations. This will be used as an
> infrastructure in the downstream patch for software communication.
>
> This will be enabled by default if CONFIG_PCI_HYPERV_MINI is set.
>
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> ---
> drivers/net/ethernet/mellanox/mlx5/core/Makefile | 1 +
> drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c | 64 ++++++++++++++++++++++++
> drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h | 22 ++++++++
> 3 files changed, 87 insertions(+)
> create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c
> create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> index 8b7edaa..a8950b1 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> @@ -45,6 +45,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offlo
> mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
> mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
> mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o
> +mlx5_core-$(CONFIG_PCI_HYPERV_MINI) += lib/hv.o
>
> #
> # Ipoib netdev
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c
> new file mode 100644
> index 0000000..cf08d02
> --- /dev/null
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
> +// Copyright (c) 2018 Mellanox Technologies
> +
> +#include <linux/hyperv.h>
> +#include "mlx5_core.h"
> +#include "lib/hv.h"
> +
> +static int mlx5_hv_config_common(struct mlx5_core_dev *dev, void *buf, int len,
> + int offset, bool read)
> +{
> + int rc = -EOPNOTSUPP;
> + int bytes_returned;
> + int block_id;
> +
> + if (offset % HV_CONFIG_BLOCK_SIZE_MAX || len % HV_CONFIG_BLOCK_SIZE_MAX)
> + return -EINVAL;
> +
> + block_id = offset / HV_CONFIG_BLOCK_SIZE_MAX;
> +
> + rc = read ?
> + hyperv_read_cfg_blk(dev->pdev, buf,
> + HV_CONFIG_BLOCK_SIZE_MAX, block_id,
> + &bytes_returned) :
> + hyperv_write_cfg_blk(dev->pdev, buf,
> + HV_CONFIG_BLOCK_SIZE_MAX, block_id);
> +
> + /* Make sure len bytes were read successfully */
> + if (read)
> + rc |= !(len == bytes_returned);
> +
> + if (rc) {
> + mlx5_core_err(dev, "Failed to %s hv config, err = %d, len = %d, offset = %d\n",
> + read ? "read" : "write", rc, len,
> + offset);
> + return rc;
> + }
> +
> + return 0;
> +}
This seems out of place why not expose this function as part of hyperv and mlx5
will just pass the pdev.
> +
> +int mlx5_hv_read_config(struct mlx5_core_dev *dev, void *buf, int len,
> + int offset)
> +{
> + return mlx5_hv_config_common(dev, buf, len, offset, true);
> +}
> +
> +int mlx5_hv_write_config(struct mlx5_core_dev *dev, void *buf, int len,
> + int offset)
> +{
> + return mlx5_hv_config_common(dev, buf, len, offset, false);
> +}
> +
> +int mlx5_hv_register_invalidate(struct mlx5_core_dev *dev, void *context,
> + void (*block_invalidate)(void *context,
> + u64 block_mask))
> +{
> + return hyperv_reg_block_invalidate(dev->pdev, context,
> + block_invalidate);
> +}
> +
> +void mlx5_hv_unregister_invalidate(struct mlx5_core_dev *dev)
> +{
> + hyperv_reg_block_invalidate(dev->pdev, NULL, NULL);
> +}
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h
> new file mode 100644
> index 0000000..7f69771
> --- /dev/null
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
> +/* Copyright (c) 2019 Mellanox Technologies. */
> +
> +#ifndef __LIB_HV_H__
> +#define __LIB_HV_H__
> +
> +#if IS_ENABLED(CONFIG_PCI_HYPERV_MINI)
> +
> +#include <linux/hyperv.h>
> +#include <linux/mlx5/driver.h>
> +
> +int mlx5_hv_read_config(struct mlx5_core_dev *dev, void *buf, int len,
> + int offset);
> +int mlx5_hv_write_config(struct mlx5_core_dev *dev, void *buf, int len,
> + int offset);
> +int mlx5_hv_register_invalidate(struct mlx5_core_dev *dev, void *context,
> + void (*block_invalidate)(void *context,
> + u64 block_mask));
> +void mlx5_hv_unregister_invalidate(struct mlx5_core_dev *dev);
> +#endif
> +
> +#endif /* __LIB_HV_H__ */
>
Mark
^ permalink raw reply
* Re: [PATCH net-next, 5/6] net/mlx5: Add HV VHCA control agent
From: Mark Bloch @ 2019-08-14 20:41 UTC (permalink / raw)
To: haiyangz, sashal@kernel.org, davem@davemloft.net, Saeed Mahameed,
leon@kernel.org, Eran Ben Elisha, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: kys, Stephen Hemminger, linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-6-git-send-email-haiyangz@microsoft.com>
On 8/14/19 12:09 PM, Haiyang Zhang wrote:
> From: Eran Ben Elisha <eranbe@mellanox.com>
>
> Control agent is responsible over of the control block (ID 0). It should
> update the PF via this block about every capability change. In addition,
> upon block 0 invalidate, it should activate all other supported agents
> with data requests from the PF.
>
> Upon agent create/destroy, the invalidate callback of the control agent
> is being called in order to update the PF driver about this change.
>
> The control agent is an integral part of HV VHCA and will be created
> and destroy as part of the HV VHCA init/cleanup flow.
>
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> ---
> .../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 122 ++++++++++++++++++++-
> .../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 1 +
> 2 files changed, 121 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
> index b2eebdf..3c7fffa 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
> @@ -110,22 +110,131 @@ void mlx5_hv_vhca_invalidate(void *context, u64 block_mask)
> queue_work(hv_vhca->work_queue, &work->invalidate_work);
> }
>
> +#define AGENT_MASK(type) (type ? BIT(type - 1) : 0 /* control */)
> +
> +static void mlx5_hv_vhca_agents_control(struct mlx5_hv_vhca *hv_vhca,
> + struct mlx5_hv_vhca_control_block *block)
> +{
> + int i;
> +
> + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) {
> + struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i];
> +
> + if (!agent || !agent->control)
> + continue;
> +
> + if (!(AGENT_MASK(agent->type) & block->control))
> + continue;
> +
> + agent->control(agent, block);
> + }
> +}
> +
> +static void mlx5_hv_vhca_capabilities(struct mlx5_hv_vhca *hv_vhca,
> + u32 *capabilities)
> +{
> + int i;
> +
> + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) {
> + struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i];
> +
> + if (agent)
> + *capabilities |= AGENT_MASK(agent->type);
> + }
> +}
> +
> +static void
> +mlx5_hv_vhca_control_agent_invalidate(struct mlx5_hv_vhca_agent *agent,
> + u64 block_mask)
> +{
> + struct mlx5_hv_vhca *hv_vhca = agent->hv_vhca;
> + struct mlx5_core_dev *dev = hv_vhca->dev;
> + struct mlx5_hv_vhca_control_block *block;
> + u32 capabilities = 0;
> + int err;
> +
> + block = kzalloc(sizeof(*block), GFP_KERNEL);
> + if (!block)
> + return;
> +
> + err = mlx5_hv_read_config(dev, block, sizeof(*block), 0);
> + if (err)
> + goto free_block;
> +
> + mlx5_hv_vhca_capabilities(hv_vhca, &capabilities);
> +
> + /* In case no capabilities, send empty block in return */
> + if (!capabilities) {
> + memset(block, 0, sizeof(*block));
> + goto write;
> + }
> +
> + if (block->capabilities != capabilities)
> + block->capabilities = capabilities;
> +
> + if (block->control & ~capabilities)
> + goto free_block;
> +
> + mlx5_hv_vhca_agents_control(hv_vhca, block);
> + block->command_ack = block->command;
> +
> +write:
> + mlx5_hv_write_config(dev, block, sizeof(*block), 0);
> +
> +free_block:
> + kfree(block);
> +}
> +
> +static struct mlx5_hv_vhca_agent *
> +mlx5_hv_vhca_control_agent_create(struct mlx5_hv_vhca *hv_vhca)
> +{
> + return mlx5_hv_vhca_agent_create(hv_vhca, MLX5_HV_VHCA_AGENT_CONTROL,
> + NULL,
> + mlx5_hv_vhca_control_agent_invalidate,
> + NULL, NULL);
> +}
> +
> +static void mlx5_hv_vhca_control_agent_destroy(struct mlx5_hv_vhca_agent *agent)
> +{
> + mlx5_hv_vhca_agent_destroy(agent);
> +}
> +
> int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca)
> {
> + struct mlx5_hv_vhca_agent *agent;
> + int err;
> +
> if (IS_ERR_OR_NULL(hv_vhca))
> return IS_ERR_OR_NULL(hv_vhca);
>
> - return mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca,
> - mlx5_hv_vhca_invalidate);
> + err = mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca,
> + mlx5_hv_vhca_invalidate);
> + if (err)
> + return err;
> +
> + agent = mlx5_hv_vhca_control_agent_create(hv_vhca);
> + if (IS_ERR_OR_NULL(agent)) {
> + mlx5_hv_unregister_invalidate(hv_vhca->dev);
> + return IS_ERR_OR_NULL(agent);
> + }
> +
> + hv_vhca->agents[MLX5_HV_VHCA_AGENT_CONTROL] = agent;
> +
> + return 0;
> }
>
> void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
> {
> + struct mlx5_hv_vhca_agent *agent;
> int i;
>
> if (IS_ERR_OR_NULL(hv_vhca))
> return;
>
> + agent = hv_vhca->agents[MLX5_HV_VHCA_AGENT_CONTROL];
> + if (!IS_ERR_OR_NULL(agent))
> + mlx5_hv_vhca_control_agent_destroy(agent);
Can the agent be err ptr here?
> +
> mutex_lock(&hv_vhca->agents_lock);
> for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++)
> WARN_ON(hv_vhca->agents[i]);
With the comment above in mind, here you check only for not null
> @@ -135,6 +244,11 @@ void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
> mlx5_hv_unregister_invalidate(hv_vhca->dev);
> }
>
> +static void mlx5_hv_vhca_agents_update(struct mlx5_hv_vhca *hv_vhca)
> +{
> + mlx5_hv_vhca_invalidate(hv_vhca, BIT(MLX5_HV_VHCA_AGENT_CONTROL));
> +}
> +
> struct mlx5_hv_vhca_agent *
> mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
> enum mlx5_hv_vhca_agent_type type,
> @@ -168,6 +282,8 @@ struct mlx5_hv_vhca_agent *
> hv_vhca->agents[type] = agent;
> mutex_unlock(&hv_vhca->agents_lock);
>
> + mlx5_hv_vhca_agents_update(hv_vhca);
> +
> return agent;
> }
>
> @@ -189,6 +305,8 @@ void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent)
> agent->cleanup(agent);
>
> kfree(agent);
> +
> + mlx5_hv_vhca_agents_update(hv_vhca);
> }
>
> static int mlx5_hv_vhca_data_block_prepare(struct mlx5_hv_vhca_agent *agent,
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
> index fa7ee85..6f4bfb1 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
> @@ -12,6 +12,7 @@
> struct mlx5_hv_vhca_control_block;
>
> enum mlx5_hv_vhca_agent_type {
> + MLX5_HV_VHCA_AGENT_CONTROL = 0,
No need to start value
> MLX5_HV_VHCA_AGENT_MAX = 32,
> };
>
>
Mark
^ permalink raw reply
* Re: [PATCH net-next, 4/6] net/mlx5: Add HV VHCA infrastructure
From: Mark Bloch @ 2019-08-14 20:41 UTC (permalink / raw)
To: haiyangz, sashal@kernel.org, davem@davemloft.net, Saeed Mahameed,
leon@kernel.org, Eran Ben Elisha, lorenzo.pieralisi@arm.com,
bhelgaas@google.com, linux-pci@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Cc: kys, Stephen Hemminger, linux-kernel@vger.kernel.org
In-Reply-To: <1565809632-39138-5-git-send-email-haiyangz@microsoft.com>
On 8/14/19 12:08 PM, Haiyang Zhang wrote:
> From: Eran Ben Elisha <eranbe@mellanox.com>
>
> HV VHCA is a layer which provides PF to VF communication channel based on
> HyperV PCI config channel. It implements Mellanox's Inter VHCA control
> communication protocol. The protocol contains control block in order to
> pass messages between the PF and VF drivers, and data blocks in order to
> pass actual data.
>
> The infrastructure is agent based. Each agent will be responsible of
> contiguous buffer blocks in the VHCA config space. This infrastructure will
> bind agents to their blocks, and those agents can only access read/write
> the buffer blocks assigned to them. Each agent will provide three
> callbacks (control, invalidate, cleanup). Control will be invoked when
> block-0 is invalidated with a command that concerns this agent. Invalidate
> callback will be invoked if one of the blocks assigned to this agent was
> invalidated. Cleanup will be invoked before the agent is being freed in
> order to clean all of its open resources or deferred works.
>
> Block-0 serves as the control block. All execution commands from the PF
> will be written by the PF over this block. VF will ack on those by
> writing on block-0 as well. Its format is described by struct
> mlx5_hv_vhca_control_block layout.
>
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> ---
> drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
> .../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c | 247 +++++++++++++++++++++
> .../net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h | 102 +++++++++
> drivers/net/ethernet/mellanox/mlx5/core/main.c | 7 +
> include/linux/mlx5/driver.h | 2 +
> 5 files changed, 359 insertions(+), 1 deletion(-)
> create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
> create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> index a8950b1..e0a1056 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
> @@ -45,7 +45,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offlo
> mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
> mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
> mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o
> -mlx5_core-$(CONFIG_PCI_HYPERV_MINI) += lib/hv.o
> +mlx5_core-$(CONFIG_PCI_HYPERV_MINI)+= lib/hv.o lib/hv_vhca.o
>
> #
> # Ipoib netdev
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
> new file mode 100644
> index 0000000..b2eebdf
> --- /dev/null
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.c
> @@ -0,0 +1,247 @@
> +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
> +// Copyright (c) 2018 Mellanox Technologies
> +
> +#include <linux/hyperv.h>
> +#include "mlx5_core.h"
> +#include "lib/hv.h"
> +#include "lib/hv_vhca.h"
> +
> +struct mlx5_hv_vhca {
> + struct mlx5_core_dev *dev;
> + struct workqueue_struct *work_queue;
> + struct mlx5_hv_vhca_agent *agents[MLX5_HV_VHCA_AGENT_MAX];
> + struct mutex agents_lock; /* Protect agents array */
> +};
> +
> +struct mlx5_hv_vhca_work {
> + struct work_struct invalidate_work;
> + struct mlx5_hv_vhca *hv_vhca;
> + u64 block_mask;
> +};
> +
> +struct mlx5_hv_vhca_data_block {
> + u16 sequence;
> + u16 offset;
> + u8 reserved[4];
> + u64 data[15];
> +};
> +
> +struct mlx5_hv_vhca_agent {
> + enum mlx5_hv_vhca_agent_type type;
> + struct mlx5_hv_vhca *hv_vhca;
> + void *priv;
> + int seq;
Why is this int? and in data block is u16?
> + void (*control)(struct mlx5_hv_vhca_agent *agent,
> + struct mlx5_hv_vhca_control_block *block);
> + void (*invalidate)(struct mlx5_hv_vhca_agent *agent,
> + u64 block_mask);
> + void (*cleanup)(struct mlx5_hv_vhca_agent *agent);
> +};
> +
> +struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev)
> +{
> + struct mlx5_hv_vhca *hv_vhca = NULL;
> +
> + hv_vhca = kzalloc(sizeof(*hv_vhca), GFP_KERNEL);
> + if (!hv_vhca)
> + return ERR_PTR(-ENOMEM);
> +
> + hv_vhca->work_queue = create_singlethread_workqueue("mlx5_hv_vhca");
> + if (!hv_vhca->work_queue) {
> + kfree(hv_vhca);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + hv_vhca->dev = dev;
> + mutex_init(&hv_vhca->agents_lock);
> +
> + return hv_vhca;
> +}
> +
> +void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca)
> +{
> + if (IS_ERR_OR_NULL(hv_vhca))
> + return;
> +
> + flush_workqueue(hv_vhca->work_queue);
> + destroy_workqueue(hv_vhca->work_queue);
Why not just destroy?
> + kfree(hv_vhca);
> +}
> +
> +static void mlx5_hv_vhca_invalidate_work(struct work_struct *work)
> +{
> + struct mlx5_hv_vhca_work *hwork;
> + struct mlx5_hv_vhca *hv_vhca;
> + int i;
> +
> + hwork = container_of(work, struct mlx5_hv_vhca_work, invalidate_work);
> + hv_vhca = hwork->hv_vhca;
> +
> + mutex_lock(&hv_vhca->agents_lock);
> + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++) {
> + struct mlx5_hv_vhca_agent *agent = hv_vhca->agents[i];
> +
> + if (!agent || !agent->invalidate)
> + continue;
> +
> + if (!(BIT(agent->type) & hwork->block_mask))
> + continue;
> +
> + agent->invalidate(agent, hwork->block_mask);
> + }
> + mutex_unlock(&hv_vhca->agents_lock);
> +
> + kfree(hwork);
> +}
> +
> +void mlx5_hv_vhca_invalidate(void *context, u64 block_mask)
> +{
> + struct mlx5_hv_vhca *hv_vhca = (struct mlx5_hv_vhca *)context;
> + struct mlx5_hv_vhca_work *work;
> +
> + work = kzalloc(sizeof(*work), GFP_ATOMIC);
> + if (!work)
> + return;
> +
> + INIT_WORK(&work->invalidate_work, mlx5_hv_vhca_invalidate_work);
> + work->hv_vhca = hv_vhca;
> + work->block_mask = block_mask;
> +
> + queue_work(hv_vhca->work_queue, &work->invalidate_work);
> +}
> +
> +int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca)
> +{
> + if (IS_ERR_OR_NULL(hv_vhca))
> + return IS_ERR_OR_NULL(hv_vhca);
> +
> + return mlx5_hv_register_invalidate(hv_vhca->dev, hv_vhca,
> + mlx5_hv_vhca_invalidate);
> +}
> +
> +void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
> +{
> + int i;
> +
> + if (IS_ERR_OR_NULL(hv_vhca))
> + return;
> +
> + mutex_lock(&hv_vhca->agents_lock);
> + for (i = 0; i < MLX5_HV_VHCA_AGENT_MAX; i++)
> + WARN_ON(hv_vhca->agents[i]);
> +
> + mutex_unlock(&hv_vhca->agents_lock);
> +
> + mlx5_hv_unregister_invalidate(hv_vhca->dev);
> +}
> +
> +struct mlx5_hv_vhca_agent *
> +mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
> + enum mlx5_hv_vhca_agent_type type,
> + void (*control)(struct mlx5_hv_vhca_agent*,
> + struct mlx5_hv_vhca_control_block *block),
> + void (*invalidate)(struct mlx5_hv_vhca_agent*,
> + u64 block_mask),
> + void (*cleaup)(struct mlx5_hv_vhca_agent *agent),
> + void *priv)
> +{
> + struct mlx5_hv_vhca_agent *agent;
> +
> + if (IS_ERR_OR_NULL(hv_vhca))
> + return ERR_PTR(-ENOMEM);
> +
> + if (hv_vhca->agents[type])
> + return ERR_PTR(-EINVAL);> +
> + agent = kzalloc(sizeof(*agent), GFP_KERNEL);
> + if (!agent)
> + return ERR_PTR(-ENOMEM);
> +
> + agent->type = type;
> + agent->hv_vhca = hv_vhca;
> + agent->priv = priv;
> + agent->control = control;
> + agent->invalidate = invalidate;
> + agent->cleanup = cleaup;
> +
> + mutex_lock(&hv_vhca->agents_lock);
> + hv_vhca->agents[type] = agent;
> + mutex_unlock(&hv_vhca->agents_lock);
You have a check for this not under a lock a few lines up,
but assign under a lock?
Mark
> +
> + return agent;
> +}
> +
> +void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent)
> +{
> + struct mlx5_hv_vhca *hv_vhca = agent->hv_vhca;
> +
> + mutex_lock(&hv_vhca->agents_lock);
> +
> + if (WARN_ON(agent != hv_vhca->agents[agent->type])) {
> + mutex_unlock(&hv_vhca->agents_lock);
> + return;
> + }
> +
> + hv_vhca->agents[agent->type] = NULL;
> + mutex_unlock(&hv_vhca->agents_lock);
> +
> + if (agent->cleanup)
> + agent->cleanup(agent);
> +
> + kfree(agent);
> +}
> +
> +static int mlx5_hv_vhca_data_block_prepare(struct mlx5_hv_vhca_agent *agent,
> + struct mlx5_hv_vhca_data_block *data_block,
> + void *src, int len, int *offset)
> +{
> + int bytes = min_t(int, (int)sizeof(data_block->data), len);
> +
> + data_block->sequence = agent->seq;
> + data_block->offset = (*offset)++;
> + memcpy(data_block->data, src, bytes);
> +
> + return bytes;
> +}
> +
> +static void mlx5_hv_vhca_agent_seq_update(struct mlx5_hv_vhca_agent *agent)
> +{
> + agent->seq++;
> +}
> +
> +int mlx5_hv_vhca_agent_write(struct mlx5_hv_vhca_agent *agent,
> + void *buf, int len)
> +{
> + int offset = agent->type * HV_CONFIG_BLOCK_SIZE_MAX;
> + int block_offset = 0;
> + int total = 0;
> + int err;
> +
> + while (len) {
> + struct mlx5_hv_vhca_data_block data_block = {0};
> + int bytes;
> +
> + bytes = mlx5_hv_vhca_data_block_prepare(agent, &data_block,
> + buf + total,
> + len, &block_offset);
> + if (!bytes)
> + return -ENOMEM;
> +
> + err = mlx5_hv_write_config(agent->hv_vhca->dev, &data_block,
> + sizeof(data_block), offset);
> + if (err)
> + return err;
> +
> + total += bytes;
> + len -= bytes;
> + }
> +
> + mlx5_hv_vhca_agent_seq_update(agent);
> +
> + return 0;
> +}
> +
> +void *mlx5_hv_vhca_agent_priv(struct mlx5_hv_vhca_agent *agent)
> +{
> + return agent->priv;
> +}
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
> new file mode 100644
> index 0000000..fa7ee85
> --- /dev/null
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/hv_vhca.h
> @@ -0,0 +1,102 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
> +/* Copyright (c) 2019 Mellanox Technologies. */
> +
> +#ifndef __LIB_HV_VHCA_H__
> +#define __LIB_HV_VHCA_H__
> +
> +#include "en.h"
> +#include "lib/hv.h"
> +
> +struct mlx5_hv_vhca_agent;
> +struct mlx5_hv_vhca;
> +struct mlx5_hv_vhca_control_block;
> +
> +enum mlx5_hv_vhca_agent_type {
> + MLX5_HV_VHCA_AGENT_MAX = 32,
> +};
> +
> +#if IS_ENABLED(CONFIG_PCI_HYPERV_MINI)
> +
> +struct mlx5_hv_vhca_control_block {
> + u32 capabilities;
> + u32 control;
> + u16 command;
> + u16 command_ack;
> + u16 version;
> + u16 rings;
> + u32 reserved1[28];
> +};
> +
> +struct mlx5_hv_vhca *mlx5_hv_vhca_create(struct mlx5_core_dev *dev);
> +void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca);
> +int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca);
> +void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca);
> +void mlx5_hv_vhca_invalidate(void *context, u64 block_mask);
> +
> +struct mlx5_hv_vhca_agent *
> +mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
> + enum mlx5_hv_vhca_agent_type type,
> + void (*control)(struct mlx5_hv_vhca_agent*,
> + struct mlx5_hv_vhca_control_block *block),
> + void (*invalidate)(struct mlx5_hv_vhca_agent*,
> + u64 block_mask),
> + void (*cleanup)(struct mlx5_hv_vhca_agent *agent),
> + void *context);
> +
> +void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent);
> +int mlx5_hv_vhca_agent_write(struct mlx5_hv_vhca_agent *agent,
> + void *buf, int len);
> +void *mlx5_hv_vhca_agent_priv(struct mlx5_hv_vhca_agent *agent);
> +
> +#else
> +
> +static inline struct mlx5_hv_vhca *
> +mlx5_hv_vhca_create(struct mlx5_core_dev *dev)
> +{
> + return NULL;
> +}
> +
> +static inline void mlx5_hv_vhca_destroy(struct mlx5_hv_vhca *hv_vhca)
> +{
> +}
> +
> +static inline int mlx5_hv_vhca_init(struct mlx5_hv_vhca *hv_vhca)
> +{
> + return 0;
> +}
> +
> +static inline void mlx5_hv_vhca_cleanup(struct mlx5_hv_vhca *hv_vhca)
> +{
> +}
> +
> +static inline void mlx5_hv_vhca_invalidate(void *context,
> + u64 block_mask)
> +{
> +}
> +
> +static inline struct mlx5_hv_vhca_agent *
> +mlx5_hv_vhca_agent_create(struct mlx5_hv_vhca *hv_vhca,
> + enum mlx5_hv_vhca_agent_type type,
> + void (*control)(struct mlx5_hv_vhca_agent*,
> + struct mlx5_hv_vhca_control_block *block),
> + void (*invalidate)(struct mlx5_hv_vhca_agent*,
> + u64 block_mask),
> + void (*cleanup)(struct mlx5_hv_vhca_agent *agent),
> + void *context)
> +{
> + return NULL;
> +}
> +
> +static inline void mlx5_hv_vhca_agent_destroy(struct mlx5_hv_vhca_agent *agent)
> +{
> +}
> +
> +static inline int
> +mlx5_hv_vhca_write_agent(struct mlx5_hv_vhca_agent *agent,
> + void *buf, int len)
> +{
> + return 0;
> +}
> +#endif
> +
> +#endif /* __LIB_HV_VHCA_H__ */
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
> index 4cc90eb..50ee38b 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
> @@ -69,6 +69,7 @@
> #include "lib/pci_vsc.h"
> #include "diag/fw_tracer.h"
> #include "ecpf.h"
> +#include "lib/hv_vhca.h"
>
> MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
> MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
> @@ -872,6 +873,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
> }
>
> dev->tracer = mlx5_fw_tracer_create(dev);
> + dev->hv_vhca = mlx5_hv_vhca_create(dev);
>
> return 0;
>
> @@ -902,6 +904,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
>
> static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
> {
> + mlx5_hv_vhca_destroy(dev->hv_vhca);
> mlx5_fw_tracer_destroy(dev->tracer);
> mlx5_fpga_cleanup(dev);
> mlx5_eswitch_cleanup(dev->priv.eswitch);
> @@ -1068,6 +1071,8 @@ static int mlx5_load(struct mlx5_core_dev *dev)
> goto err_fw_tracer;
> }
>
> + mlx5_hv_vhca_init(dev->hv_vhca);
> +
> err = mlx5_fpga_device_start(dev);
> if (err) {
> mlx5_core_err(dev, "fpga device start failed %d\n", err);
> @@ -1123,6 +1128,7 @@ static int mlx5_load(struct mlx5_core_dev *dev)
> err_ipsec_start:
> mlx5_fpga_device_stop(dev);
> err_fpga_start:
> + mlx5_hv_vhca_cleanup(dev->hv_vhca);
> mlx5_fw_tracer_cleanup(dev->tracer);
> err_fw_tracer:
> mlx5_eq_table_destroy(dev);
> @@ -1143,6 +1149,7 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
> mlx5_accel_ipsec_cleanup(dev);
> mlx5_accel_tls_cleanup(dev);
> mlx5_fpga_device_stop(dev);
> + mlx5_hv_vhca_cleanup(dev->hv_vhca);
> mlx5_fw_tracer_cleanup(dev->tracer);
> mlx5_eq_table_destroy(dev);
> mlx5_irq_table_destroy(dev);
> diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
> index 2b84ee9..97bb98c 100644
> --- a/include/linux/mlx5/driver.h
> +++ b/include/linux/mlx5/driver.h
> @@ -646,6 +646,7 @@ struct mlx5_clock {
> struct mlx5_fw_tracer;
> struct mlx5_vxlan;
> struct mlx5_geneve;
> +struct mlx5_hv_vhca;
>
> struct mlx5_core_dev {
> struct device *device;
> @@ -693,6 +694,7 @@ struct mlx5_core_dev {
> struct mlx5_ib_clock_info *clock_info;
> struct mlx5_fw_tracer *tracer;
> u32 vsc_addr;
> + struct mlx5_hv_vhca *hv_vhca;
> };
>
> struct mlx5_db {
>
^ permalink raw reply
* [PATCH v5 00/18] compat_ioctl.c removal, part 2/3
From: Arnd Bergmann @ 2019-08-14 20:42 UTC (permalink / raw)
To: linux-kernel, viro, linux-fsdevel
Cc: Arnd Bergmann, davem, axboe, linux-block, minyard, gregkh, linux,
alexandre.belloni, jejb, martin.petersen, dgilbert, jslaby, wim,
tytso, adilger.kernel, jaegeuk, rpeterso, agruenba, mikulas,
konishi.ryusuke, jlbec, joseph.qi, darrick.wong, linux-xfs,
netdev, openipmi-developer, linux-hwmon, linux-ppp, linux-rtc,
linux-scsi, linux-watchdog, ecryptfs, linux-ext4,
linux-f2fs-devel, cluster-devel, linux-nilfs, ocfs2-devel
This is a follow-up to part 1/3 that I posted after -rc2.
I hope these are still largely uncontroversial changes, and
I would like to get them into linux-5.4.
Part 1 was in
https://lore.kernel.org/lkml/CAPcyv4i_nHzV155RcgnAQ189aq2Lfd2g8pA1D5NbZqo9E_u+Dw@mail.gmail.com/
Part 3 will be one kernel release after part 2 is merged,
as that still needs a little extra work.
The entire series is available at
git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git compat_ioctl
Arnd
Al Viro (2):
compat_ioctl: unify copy-in of ppp filters
compat_ioctl: move PPPIOCSCOMPRESS to ppp_generic
Arnd Bergmann (16):
xfs: compat_ioctl: use compat_ptr()
xfs: compat_ioctl: add missing conversions
gfs2: add compat_ioctl support
fs: compat_ioctl: move FITRIM emulation into file systems
watchdog: cpwd: use generic compat_ptr_ioctl
compat_ioctl: move WDIOC handling into wdt drivers
compat_ioctl: reimplement SG_IO handling
af_unix: add compat_ioctl support
compat_ioctl: handle SIOCOUTQNSD
compat_ioctl: move SIOCOUTQ out of compat_ioctl.c
tty: handle compat PPP ioctls
compat_ioctl: handle PPPIOCGIDLE for 64-bit time_t
compat_ioctl: ppp: move simple commands into ppp_generic.c
compat_ioctl: move SG_GET_REQUEST_TABLE handling
pktcdvd: add compat_ioctl handler
scsi: sd: enable compat ioctls for sed-opal
Documentation/networking/ppp_generic.txt | 2 +
arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1 +
arch/um/drivers/harddog_kern.c | 1 +
block/scsi_ioctl.c | 132 ++++++++-
drivers/block/pktcdvd.c | 25 ++
drivers/char/ipmi/ipmi_watchdog.c | 1 +
drivers/hwmon/fschmd.c | 1 +
drivers/net/ppp/ppp_generic.c | 245 ++++++++++-----
drivers/rtc/rtc-ds1374.c | 1 +
drivers/scsi/sd.c | 14 +-
drivers/scsi/sg.c | 59 +++-
drivers/tty/tty_io.c | 5 +
drivers/watchdog/acquirewdt.c | 1 +
drivers/watchdog/advantechwdt.c | 1 +
drivers/watchdog/alim1535_wdt.c | 1 +
drivers/watchdog/alim7101_wdt.c | 1 +
drivers/watchdog/ar7_wdt.c | 1 +
drivers/watchdog/at91rm9200_wdt.c | 1 +
drivers/watchdog/ath79_wdt.c | 1 +
drivers/watchdog/bcm63xx_wdt.c | 1 +
drivers/watchdog/cpu5wdt.c | 1 +
drivers/watchdog/cpwd.c | 25 +-
drivers/watchdog/eurotechwdt.c | 1 +
drivers/watchdog/f71808e_wdt.c | 1 +
drivers/watchdog/gef_wdt.c | 1 +
drivers/watchdog/geodewdt.c | 1 +
drivers/watchdog/ib700wdt.c | 1 +
drivers/watchdog/ibmasr.c | 1 +
drivers/watchdog/indydog.c | 1 +
drivers/watchdog/intel_scu_watchdog.c | 1 +
drivers/watchdog/iop_wdt.c | 1 +
drivers/watchdog/it8712f_wdt.c | 1 +
drivers/watchdog/ixp4xx_wdt.c | 1 +
drivers/watchdog/ks8695_wdt.c | 1 +
drivers/watchdog/m54xx_wdt.c | 1 +
drivers/watchdog/machzwd.c | 1 +
drivers/watchdog/mixcomwd.c | 1 +
drivers/watchdog/mtx-1_wdt.c | 1 +
drivers/watchdog/mv64x60_wdt.c | 1 +
drivers/watchdog/nuc900_wdt.c | 1 +
drivers/watchdog/nv_tco.c | 1 +
drivers/watchdog/pc87413_wdt.c | 1 +
drivers/watchdog/pcwd.c | 1 +
drivers/watchdog/pcwd_pci.c | 1 +
drivers/watchdog/pcwd_usb.c | 1 +
drivers/watchdog/pika_wdt.c | 1 +
drivers/watchdog/pnx833x_wdt.c | 1 +
drivers/watchdog/rc32434_wdt.c | 1 +
drivers/watchdog/rdc321x_wdt.c | 1 +
drivers/watchdog/riowd.c | 1 +
drivers/watchdog/sa1100_wdt.c | 1 +
drivers/watchdog/sb_wdog.c | 1 +
drivers/watchdog/sbc60xxwdt.c | 1 +
drivers/watchdog/sbc7240_wdt.c | 1 +
drivers/watchdog/sbc_epx_c3.c | 1 +
drivers/watchdog/sbc_fitpc2_wdt.c | 1 +
drivers/watchdog/sc1200wdt.c | 1 +
drivers/watchdog/sc520_wdt.c | 1 +
drivers/watchdog/sch311x_wdt.c | 1 +
drivers/watchdog/scx200_wdt.c | 1 +
drivers/watchdog/smsc37b787_wdt.c | 1 +
drivers/watchdog/w83877f_wdt.c | 1 +
drivers/watchdog/w83977f_wdt.c | 1 +
drivers/watchdog/wafer5823wdt.c | 1 +
drivers/watchdog/watchdog_dev.c | 1 +
drivers/watchdog/wdrtas.c | 1 +
drivers/watchdog/wdt.c | 1 +
drivers/watchdog/wdt285.c | 1 +
drivers/watchdog/wdt977.c | 1 +
drivers/watchdog/wdt_pci.c | 1 +
fs/compat_ioctl.c | 346 +---------------------
fs/ecryptfs/file.c | 1 +
fs/ext4/ioctl.c | 1 +
fs/f2fs/file.c | 1 +
fs/gfs2/file.c | 24 ++
fs/hpfs/dir.c | 1 +
fs/hpfs/file.c | 1 +
fs/nilfs2/ioctl.c | 1 +
fs/ocfs2/ioctl.c | 1 +
fs/xfs/xfs_ioctl32.c | 11 +-
include/linux/blkdev.h | 2 +
include/uapi/linux/ppp-ioctl.h | 2 +
include/uapi/linux/ppp_defs.h | 14 +
lib/iov_iter.c | 1 +
net/socket.c | 3 +
net/unix/af_unix.c | 19 ++
86 files changed, 526 insertions(+), 472 deletions(-)
--
2.20.0
Cc: davem@davemloft.net
Cc: axboe@kernel.dk
Cc: linux-block@vger.kernel.org
Cc: minyard@acm.org
Cc: gregkh@linuxfoundation.org
Cc: linux@roeck-us.net
Cc: alexandre.belloni@bootlin.com
Cc: jejb@linux.ibm.com
Cc: martin.petersen@oracle.com
Cc: dgilbert@interlog.com
Cc: jslaby@suse.com
Cc: wim@linux-watchdog.org
Cc: viro@zeniv.linux.org.uk
Cc: tytso@mit.edu
Cc: adilger.kernel@dilger.ca
Cc: jaegeuk@kernel.org
Cc: rpeterso@redhat.com
Cc: agruenba@redhat.com
Cc: mikulas@artax.karlin.mff.cuni.cz
Cc: konishi.ryusuke@gmail.com
Cc: jlbec@evilplan.org
Cc: joseph.qi@linux.alibaba.com
Cc: darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: openipmi-developer@lists.sourceforge.net
Cc: linux-hwmon@vger.kernel.org
Cc: linux-ppp@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
Cc: linux-scsi@vger.kernel.org
Cc: linux-watchdog@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: ecryptfs@vger.kernel.org
Cc: linux-ext4@vger.kernel.org
Cc: linux-f2fs-devel@lists.sourceforge.net
Cc: cluster-devel@redhat.com
Cc: linux-nilfs@vger.kernel.org
Cc: ocfs2-devel@oss.oracle.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox