Netdev List
 help / color / mirror / Atom feed
* [PATCH mlx5-next 3/8] net/mlx5: Add core support for double vlan push/pop steering action
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Jianbo Liu, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Jianbo Liu <jianbol@mellanox.com>

As newer firmware supports double push/pop in a single FTE, we add
core bits and extend vlan action logic for it.

Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 .../ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h |  2 ++
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c   |  6 +++---
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c     | 12 +++++++++---
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c    |  4 +++-
 include/linux/mlx5/fs.h                              |  4 +++-
 include/linux/mlx5/mlx5_ifc.h                        | 11 +++++++++--
 6 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
index 09f178a3fcab..0240aee9189e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
@@ -138,6 +138,8 @@ TRACE_EVENT(mlx5_fs_del_fg,
 	{MLX5_FLOW_CONTEXT_ACTION_MOD_HDR,	 "MOD_HDR"},\
 	{MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH,	 "VLAN_PUSH"},\
 	{MLX5_FLOW_CONTEXT_ACTION_VLAN_POP,	 "VLAN_POP"},\
+	{MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2,	 "VLAN_PUSH_2"},\
+	{MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2,	 "VLAN_POP_2"},\
 	{MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO, "NEXT_PRIO"}
 
 TRACE_EVENT(mlx5_fs_set_fte,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index cecd201f0b73..8f50ce80ff66 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -70,9 +70,9 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 		flow_act.action &= ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
 				     MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
 	else if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
-		flow_act.vlan.ethtype = ntohs(attr->vlan_proto);
-		flow_act.vlan.vid = attr->vlan_vid;
-		flow_act.vlan.prio = attr->vlan_prio;
+		flow_act.vlan[0].ethtype = ntohs(attr->vlan_proto);
+		flow_act.vlan[0].vid = attr->vlan_vid;
+		flow_act.vlan[0].prio = attr->vlan_prio;
 	}
 
 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index 5a00deff5457..6a62b84e57f4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -349,9 +349,15 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
 
 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan);
 
-	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan.ethtype);
-	MLX5_SET(vlan, vlan, vid, fte->action.vlan.vid);
-	MLX5_SET(vlan, vlan, prio, fte->action.vlan.prio);
+	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype);
+	MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid);
+	MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio);
+
+	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2);
+
+	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype);
+	MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid);
+	MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio);
 
 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
 				      match_value);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 49a75d31185e..05e7a5112b74 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -1464,7 +1464,9 @@ static bool check_conflicting_actions(u32 action1, u32 action2)
 			     MLX5_FLOW_CONTEXT_ACTION_DECAP |
 			     MLX5_FLOW_CONTEXT_ACTION_MOD_HDR  |
 			     MLX5_FLOW_CONTEXT_ACTION_VLAN_POP |
-			     MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH))
+			     MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH |
+			     MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2 |
+			     MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2))
 		return true;
 
 	return false;
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
index 757b4a30281e..c40f2fc68655 100644
--- a/include/linux/mlx5/fs.h
+++ b/include/linux/mlx5/fs.h
@@ -152,6 +152,8 @@ struct mlx5_fs_vlan {
         u8  prio;
 };
 
+#define MLX5_FS_VLAN_DEPTH	2
+
 struct mlx5_flow_act {
 	u32 action;
 	bool has_flow_tag;
@@ -159,7 +161,7 @@ struct mlx5_flow_act {
 	u32 encap_id;
 	u32 modify_id;
 	uintptr_t esp_id;
-	struct mlx5_fs_vlan vlan;
+	struct mlx5_fs_vlan vlan[MLX5_FS_VLAN_DEPTH];
 	struct ib_counters *counters;
 };
 
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 2de5feaeb74a..ae12120ef021 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -337,7 +337,10 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
 	u8         reserved_at_9[0x1];
 	u8         pop_vlan[0x1];
 	u8         push_vlan[0x1];
-	u8         reserved_at_c[0x14];
+	u8         reserved_at_c[0x1];
+	u8         pop_vlan_2[0x1];
+	u8         push_vlan_2[0x1];
+	u8         reserved_at_f[0x11];
 
 	u8         reserved_at_20[0x2];
 	u8         log_max_ft_size[0x6];
@@ -2386,6 +2389,8 @@ enum {
 	MLX5_FLOW_CONTEXT_ACTION_MOD_HDR   = 0x40,
 	MLX5_FLOW_CONTEXT_ACTION_VLAN_POP  = 0x80,
 	MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH = 0x100,
+	MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2  = 0x400,
+	MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 = 0x800,
 };
 
 struct mlx5_ifc_vlan_bits {
@@ -2416,7 +2421,9 @@ struct mlx5_ifc_flow_context_bits {
 
 	u8         modify_header_id[0x20];
 
-	u8         reserved_at_100[0x100];
+	struct mlx5_ifc_vlan_bits push_vlan_2;
+
+	u8         reserved_at_120[0xe0];
 
 	struct mlx5_ifc_fte_match_param_bits match_value;
 
-- 
2.17.0

^ permalink raw reply related

* [PATCH mlx5-next 2/8] net/mlx5: Expose MPEGC (Management PCIe General Configuration) structures
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Eran Ben Elisha, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Eran Ben Elisha <eranbe@mellanox.com>

This patch exposes PRM layout for handling MPEGC (Management PCIe
General Configuration).

This will be used in the downstream patch for configuring MPEGC via the
driver.

Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 include/linux/mlx5/driver.h   |  1 +
 include/linux/mlx5/mlx5_ifc.h | 23 +++++++++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 4a4125b4279d..957199c20a0f 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -145,6 +145,7 @@ enum {
 	MLX5_REG_MPCNT		 = 0x9051,
 	MLX5_REG_MTPPS		 = 0x9053,
 	MLX5_REG_MTPPSE		 = 0x9054,
+	MLX5_REG_MPEGC		 = 0x9056,
 	MLX5_REG_MCQI		 = 0x9061,
 	MLX5_REG_MCC		 = 0x9062,
 	MLX5_REG_MCDA		 = 0x9063,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index bd7b71f54d59..2de5feaeb74a 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -8049,6 +8049,19 @@ struct mlx5_ifc_peir_reg_bits {
 	u8         error_type[0x8];
 };
 
+struct mlx5_ifc_mpegc_reg_bits {
+	u8         reserved_at_0[0x30];
+	u8         field_select[0x10];
+
+	u8         tx_overflow_sense[0x1];
+	u8         mark_cqe[0x1];
+	u8         mark_cnp[0x1];
+	u8         reserved_at_43[0x1b];
+	u8         tx_lossy_overflow_oper[0x2];
+
+	u8         reserved_at_60[0x100];
+};
+
 struct mlx5_ifc_pcam_enhanced_features_bits {
 	u8         reserved_at_0[0x6d];
 	u8         rx_icrc_encapsulated_counter[0x1];
@@ -8097,7 +8110,11 @@ struct mlx5_ifc_pcam_reg_bits {
 };
 
 struct mlx5_ifc_mcam_enhanced_features_bits {
-	u8         reserved_at_0[0x7b];
+	u8         reserved_at_0[0x74];
+	u8         mark_tx_action_cnp[0x1];
+	u8         mark_tx_action_cqe[0x1];
+	u8         dynamic_tx_overflow[0x1];
+	u8         reserved_at_77[0x4];
 	u8         pcie_outbound_stalled[0x1];
 	u8         tx_overflow_buffer_pkt[0x1];
 	u8         mtpps_enh_out_per_adj[0x1];
@@ -8112,7 +8129,9 @@ struct mlx5_ifc_mcam_access_reg_bits {
 	u8         mcqi[0x1];
 	u8         reserved_at_1f[0x1];
 
-	u8         regs_95_to_68[0x1c];
+	u8         regs_95_to_87[0x9];
+	u8         mpegc[0x1];
+	u8         regs_85_to_68[0x12];
 	u8         tracer_registers[0x4];
 
 	u8         regs_63_to_32[0x20];
-- 
2.17.0

^ permalink raw reply related

* [PATCH mlx5-next 4/8] net/mlx5: Add XRQ commands definitions
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Max Gurtovoy, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Max Gurtovoy <maxg@mellanox.com>

Update mlx5 command list and error return function to handle XRQ
commands.

Signed-off-by: Max Gurtovoy <maxg@mellanox.com>
Reviewed-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Artemy Kovalyov <artemyko@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index a94955302482..10517b2a0643 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -278,6 +278,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_DESTROY_PSV:
 	case MLX5_CMD_OP_DESTROY_SRQ:
 	case MLX5_CMD_OP_DESTROY_XRC_SRQ:
+	case MLX5_CMD_OP_DESTROY_XRQ:
 	case MLX5_CMD_OP_DESTROY_DCT:
 	case MLX5_CMD_OP_DEALLOC_Q_COUNTER:
 	case MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT:
@@ -347,6 +348,9 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_CREATE_XRC_SRQ:
 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
 	case MLX5_CMD_OP_ARM_XRC_SRQ:
+	case MLX5_CMD_OP_CREATE_XRQ:
+	case MLX5_CMD_OP_QUERY_XRQ:
+	case MLX5_CMD_OP_ARM_XRQ:
 	case MLX5_CMD_OP_CREATE_DCT:
 	case MLX5_CMD_OP_DRAIN_DCT:
 	case MLX5_CMD_OP_QUERY_DCT:
@@ -601,6 +605,10 @@ const char *mlx5_command_str(int command)
 	MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP);
 	MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP_COUNTERS);
 	MLX5_COMMAND_STR_CASE(FPGA_DESTROY_QP);
+	MLX5_COMMAND_STR_CASE(CREATE_XRQ);
+	MLX5_COMMAND_STR_CASE(DESTROY_XRQ);
+	MLX5_COMMAND_STR_CASE(QUERY_XRQ);
+	MLX5_COMMAND_STR_CASE(ARM_XRQ);
 	MLX5_COMMAND_STR_CASE(CREATE_GENERAL_OBJECT);
 	MLX5_COMMAND_STR_CASE(DESTROY_GENERAL_OBJECT);
 	default: return "unknown command opcode";
-- 
2.17.0

^ permalink raw reply related

* [PATCH mlx5-next 5/8] net/mlx5: Add missing SET_DRIVER_VERSION command translation
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Noa Osherovich, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Noa Osherovich <noaos@mellanox.com>

When translating command opcodes to a string, SET_DRIVER_VERSION
command was missing.

Fixes: 42ca502e179d0 ('net/mlx5_core: Use a macro in mlx5_command_str()')
Signed-off-by: Noa Osherovich <noaos@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 10517b2a0643..041c18faea46 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -458,6 +458,7 @@ const char *mlx5_command_str(int command)
 	MLX5_COMMAND_STR_CASE(SET_HCA_CAP);
 	MLX5_COMMAND_STR_CASE(QUERY_ISSI);
 	MLX5_COMMAND_STR_CASE(SET_ISSI);
+	MLX5_COMMAND_STR_CASE(SET_DRIVER_VERSION);
 	MLX5_COMMAND_STR_CASE(CREATE_MKEY);
 	MLX5_COMMAND_STR_CASE(QUERY_MKEY);
 	MLX5_COMMAND_STR_CASE(DESTROY_MKEY);
-- 
2.17.0

^ permalink raw reply related

* [PATCH mlx5-next 7/8] net/mlx5: Better return types for CQE API
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Tariq Toukan, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Tariq Toukan <tariqt@mellanox.com>

Reduce sizes of return types.
Use bool for binary indication.

Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 include/linux/mlx5/device.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index f8671c0a43aa..0566c6a94805 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -750,7 +750,7 @@ enum {
 
 #define MLX5_MINI_CQE_ARRAY_SIZE 8
 
-static inline int mlx5_get_cqe_format(struct mlx5_cqe64 *cqe)
+static inline u8 mlx5_get_cqe_format(struct mlx5_cqe64 *cqe)
 {
 	return (cqe->op_own >> 2) & 0x3;
 }
@@ -770,14 +770,14 @@ static inline u8 get_cqe_l3_hdr_type(struct mlx5_cqe64 *cqe)
 	return (cqe->l4_l3_hdr_type >> 2) & 0x3;
 }
 
-static inline u8 cqe_is_tunneled(struct mlx5_cqe64 *cqe)
+static inline bool cqe_is_tunneled(struct mlx5_cqe64 *cqe)
 {
 	return cqe->outer_l3_tunneled & 0x1;
 }
 
-static inline int cqe_has_vlan(struct mlx5_cqe64 *cqe)
+static inline bool cqe_has_vlan(struct mlx5_cqe64 *cqe)
 {
-	return !!(cqe->l4_l3_hdr_type & 0x1);
+	return cqe->l4_l3_hdr_type & 0x1;
 }
 
 static inline u64 get_cqe_ts(struct mlx5_cqe64 *cqe)
-- 
2.17.0

^ permalink raw reply related

* [PATCH mlx5-next 6/8] net/mlx5: Use ERR_CAST() instead of coding it
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Roi Dayan, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Roi Dayan <roid@mellanox.com>

This makes it more readable that rule is being used to return an err.

Signed-off-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 05e7a5112b74..29b86232f13a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -1825,7 +1825,7 @@ _mlx5_add_flow_rules(struct mlx5_flow_table *ft,
 
 	g = alloc_auto_flow_group(ft, spec);
 	if (IS_ERR(g)) {
-		rule = (void *)g;
+		rule = ERR_CAST(g);
 		up_write_ref_node(&ft->node);
 		return rule;
 	}
-- 
2.17.0

^ permalink raw reply related

* [PATCH mlx5-next 8/8] net/mlx5: Fix tristate and description for MLX5 module
From: Saeed Mahameed @ 2018-07-17  1:35 UTC (permalink / raw)
  To: netdev, linux-rdma
  Cc: David S. Miller, Doug Ledford, Jason Gunthorpe, Leon Romanovsky,
	Eran Ben Elisha, Saeed Mahameed
In-Reply-To: <20180717013537.26411-1-saeedm@mellanox.com>

From: Eran Ben Elisha <eranbe@mellanox.com>

Current description did not include new devices. Fix that by proving the
correct generic description.

Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/infiniband/hw/mlx5/Kconfig              | 2 +-
 drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 6 +++---
 drivers/net/ethernet/mellanox/mlx5/core/main.c  | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/Kconfig b/drivers/infiniband/hw/mlx5/Kconfig
index fb4d77be019b..0440966bc6ec 100644
--- a/drivers/infiniband/hw/mlx5/Kconfig
+++ b/drivers/infiniband/hw/mlx5/Kconfig
@@ -1,5 +1,5 @@
 config MLX5_INFINIBAND
-	tristate "Mellanox Connect-IB HCA support"
+	tristate "Mellanox 5th generation network adapters (ConnectX series) support"
 	depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
 	depends on INFINIBAND_USER_ACCESS || INFINIBAND_USER_ACCESS=n
 	---help---
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index 2545296a0c08..7a84dd07ced2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -3,7 +3,7 @@
 #
 
 config MLX5_CORE
-	tristate "Mellanox Technologies ConnectX-4 and Connect-IB core driver"
+	tristate "Mellanox 5th generation network adapters (ConnectX series) core driver"
 	depends on MAY_USE_DEVLINK
 	depends on PCI
 	imply PTP_1588_CLOCK
@@ -27,7 +27,7 @@ config MLX5_FPGA
           sandbox-specific client drivers.
 
 config MLX5_CORE_EN
-	bool "Mellanox Technologies ConnectX-4 Ethernet support"
+	bool "Mellanox 5th generation network adapters (ConnectX series) Ethernet support"
 	depends on NETDEVICES && ETHERNET && INET && PCI && MLX5_CORE
 	depends on IPV6=y || IPV6=n || MLX5_CORE=m
 	select PAGE_POOL
@@ -69,7 +69,7 @@ config MLX5_CORE_EN_DCB
 	  If unsure, set to Y
 
 config MLX5_CORE_IPOIB
-	bool "Mellanox Technologies ConnectX-4 IPoIB offloads support"
+	bool "Mellanox 5th generation network adapters (connectX series) IPoIB offloads support"
 	depends on MLX5_CORE_EN
 	default n
 	---help---
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 615005e63819..f9b950e1bd85 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -64,7 +64,7 @@
 #include "lib/clock.h"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
-MODULE_DESCRIPTION("Mellanox Connect-IB, ConnectX-4 core driver");
+MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRIVER_VERSION);
 
-- 
2.17.0

^ permalink raw reply related

* Re: [RFC PATCH 0/1] net: phy: skip autoneg of ethernet(fec) on network boot
From: Masahiko KIMOTO @ 2018-07-17  1:47 UTC (permalink / raw)
  To: andrew; +Cc: f.fainelli, fugang.duan, netdev, linux-kernel, hiraku.toyooka
In-Reply-To: <20180710.105230.2160849304208584873.kimoto@cybertrust.co.jp>

  >   > You said that the PHY is being configured 3 times, and might be doing
  >   > auto-neg three times. Often a phy will not actually perform auto-neg,
  >   > or do it much faster, if the advertised bits do not change with each
  >   > re-configuration.
  >   > 
  >   > So check how u-boot is configuring what is advertised, and look at
  >   > what Linux is configuring. In particularly, look at the pause
  >   > configuration. If pause is configured different in u-boot and Linux,
  >   > try to make it the same. Things might go faster than.
  > 
  > Thank you.
  > 
  > I'll try to check out u-boot side by mii command and Linux(server)
  > side by ethtool.

PHY setting in u-boot and after booting Linux is as follows;

We may avoid second and third auto-neg if both settings in u-boot and
in linux make same value, right?

---------------------------------------------------------------------------
=> mii dump 1 4
4.     (11e1)                 -- Autonegotiation advertisement register --
  (8000:0000) 4.15    =     0    next page able
  (4000:0000) 4.14    =     0    (reserved)
  (2000:0000) 4.13    =     0    remote fault
  (1000:1000) 4.12    =     1    (reserved)
  (0800:0000) 4.11    =     0    asymmetric pause
  (0400:0000) 4.10    =     0    pause enable
  (0200:0000) 4. 9    =     0    100BASE-T4 able
  (0100:0100) 4. 8    =     1    100BASE-TX full duplex able
  (0080:0080) 4. 7    =     1    100BASE-TX able
  (0040:0040) 4. 6    =     1    10BASE-T   full duplex able
  (0020:0020) 4. 5    =     1    10BASE-T   able
  (001f:0001) 4. 4- 0 =     1    selector = IEEE 802.3


=> mii dump 1 5
5.     (dd01)                 -- Autonegotiation partner abilities register --
  (8000:8000) 5.15    =     1    next page able
  (4000:4000) 5.14    =     1    acknowledge
  (2000:0000) 5.13    =     0    remote fault
  (1000:1000) 5.12    =     1    (reserved)
  (0800:0800) 5.11    =     1    asymmetric pause able
  (0400:0400) 5.10    =     1    pause able
  (0200:0000) 5. 9    =     0    100BASE-T4 able
  (0100:0100) 5. 8    =     1    100BASE-X full duplex able
  (0080:0000) 5. 7    =     0    100BASE-TX able
  (0040:0000) 5. 6    =     0    10BASE-T full duplex able
  (0020:0000) 5. 5    =     0    10BASE-T able
  (001f:0001) 5. 4- 0 =     1    selector = IEEE 802.3

---------------------------------------------------------------------------
root@imx6qdlsabresd:~# ethtool eth0
Settings for eth0:
        Supported ports: [ TP MII ]
        Supported link modes:   10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Full 
        Supported pause frame use: Symmetric
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Full 
        Advertised pause frame use: Symmetric
        Advertised auto-negotiation: Yes
        Link partner advertised link modes:  100baseT/Full 
                                             1000baseT/Full 
        Link partner advertised pause frame use: Symmetric Receive-only
        Link partner advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: MII
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: d
        Wake-on: d
        Link detected: yes

root@imx6qdlsabresd:~# ethtool -a eth0
Pause parameters for eth0:
Autonegotiate:  on
RX:             off
TX:             off
RX negotiated:  on
TX negotiated:  on

---------------------------------------------------------------------------

---------------------------------------------------------------------------
Masahiko KIMOTO,Ph.D. / Cybertrust Japan Co., Ltd. 
mail: masahiko.kimoto@cybertrust.co.jp
web: https://www.cybertrust.co.jp/ https://www.miraclelinux.com/

^ permalink raw reply

* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2018-07-17  2:33 UTC (permalink / raw)
  To: David Miller, Networking
  Cc: Linux-Next Mailing List, Linux Kernel Mailing List,
	Stefano Brivio, Boris Pismenny

[-- Attachment #1: Type: text/plain, Size: 1783 bytes --]

Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  include/linux/skbuff.h

between commit:

  8b7008620b84 ("net: Don't copy pfmemalloc flag in __copy_skb_header()")

from the net tree and commit:

  784abe24c903 ("net: Add decrypted field to skb")

from the net-next tree.

I fixed it up (see below - maybe not the best resolution) and can carry
the fix as necessary. This is now fixed as far as linux-next is
concerned, but any non trivial conflicts should be mentioned to your
upstream maintainer when your tree is submitted for merging.  You may
also want to consider cooperating with the maintainer of the
conflicting tree to minimise any particularly complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc include/linux/skbuff.h
index 610a201126ee,3ceb8dcc54da..000000000000
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@@ -630,7 -630,7 +630,8 @@@ typedef unsigned char *sk_buff_data_t
   *	@hash: the packet hash
   *	@queue_mapping: Queue mapping for multiqueue devices
   *	@xmit_more: More SKBs are pending for this queue
 + *	@pfmemalloc: skbuff was allocated from PFMEMALLOC reserves
+  *	@decrypted: Decrypted SKB
   *	@ndisc_nodetype: router type (from link layer)
   *	@ooo_okay: allow the mapping of a socket to a queue to be changed
   *	@l4_hash: indicate hash is a canonical 4-tuple hash over transport
@@@ -736,7 -737,11 +738,11 @@@ struct sk_buff 
  				peeked:1,
  				head_frag:1,
  				xmit_more:1,
 +				pfmemalloc:1;
+ #ifdef CONFIG_TLS_DEVICE
 -				decrypted:1;
 -#else
 -				__unused:1;
++	__u8			decrypted:1,
++				__unused:7;
+ #endif
  
  	/* fields enclosed in headers_start/headers_end are copied
  	 * using a single memcpy() in __copy_skb_header()

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH net-next] xdp: fix uninitialized 'err' variable
From: Jakub Kicinski @ 2018-07-17  2:08 UTC (permalink / raw)
  To: davem
  Cc: daniel, alexei.starovoitov, kbuild-all, oss-drivers, netdev,
	Jakub Kicinski
In-Reply-To: <20180717015758.GB10593@intel.com>

Smatch caught an uninitialized variable error which GCC seems
to miss.

Fixes: a25717d2b604 ("xdp: support simultaneous driver and hw XDP attachment")
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 net/core/rtnetlink.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e03258e954c8..92b6fa5d5f6e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1414,14 +1414,17 @@ static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
 
 	prog_id = 0;
 	mode = XDP_ATTACHED_NONE;
-	if (rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_SKB,
-				IFLA_XDP_SKB_PROG_ID, rtnl_xdp_prog_skb))
+	err = rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_SKB,
+				  IFLA_XDP_SKB_PROG_ID, rtnl_xdp_prog_skb);
+	if (err)
 		goto err_cancel;
-	if (rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_DRV,
-				IFLA_XDP_DRV_PROG_ID, rtnl_xdp_prog_drv))
+	err = rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_DRV,
+				  IFLA_XDP_DRV_PROG_ID, rtnl_xdp_prog_drv);
+	if (err)
 		goto err_cancel;
-	if (rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_HW,
-				IFLA_XDP_HW_PROG_ID, rtnl_xdp_prog_hw))
+	err = rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_HW,
+				  IFLA_XDP_HW_PROG_ID, rtnl_xdp_prog_hw);
+	if (err)
 		goto err_cancel;
 
 	err = nla_put_u8(skb, IFLA_XDP_ATTACHED, mode);
-- 
2.17.1

^ permalink raw reply related

* [net-next:master 238/243] drivers/net/phy/mdio-thunder.c:40:8: error: implicit declaration of function 'pcim_enable_device'; did you mean 'pci_enable_device'?
From: kbuild test robot @ 2018-07-17  2:37 UTC (permalink / raw)
  To: Alexander Sverdlin; +Cc: kbuild-all, netdev

[-- Attachment #1: Type: text/plain, Size: 34365 bytes --]

Hi Alexander,

First bad commit (maybe != root cause):

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head:   ccdb51717ba3bdc9585998e4ffd41d70c04dedea
commit: 7e2bc7fb65d544bb8598a0ab64e40ee9c60ded6e [238/243] net: cavium: Drop dependency of NET_VENDOR_CAVIUM on PCI
config: um-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        git checkout 7e2bc7fb65d544bb8598a0ab64e40ee9c60ded6e
        # save the attached .config to linux build tree
        make ARCH=um 

All error/warnings (new ones prefixed by >>):

   drivers/net/phy/mdio-thunder.c: In function 'thunder_mdiobus_pci_probe':
>> drivers/net/phy/mdio-thunder.c:40:8: error: implicit declaration of function 'pcim_enable_device'; did you mean 'pci_enable_device'? [-Werror=implicit-function-declaration]
     err = pcim_enable_device(pdev);
           ^~~~~~~~~~~~~~~~~~
           pci_enable_device
   drivers/net/phy/mdio-thunder.c: At top level:
>> drivers/net/phy/mdio-thunder.c:151:1: warning: data definition has no type or storage class
    module_pci_driver(thunder_mdiobus_driver);
    ^~~~~~~~~~~~~~~~~
>> drivers/net/phy/mdio-thunder.c:151:1: error: type defaults to 'int' in declaration of 'module_pci_driver' [-Werror=implicit-int]
>> drivers/net/phy/mdio-thunder.c:151:1: warning: parameter names (without types) in function declaration
   drivers/net/phy/mdio-thunder.c:144:26: warning: 'thunder_mdiobus_driver' defined but not used [-Wunused-variable]
    static struct pci_driver thunder_mdiobus_driver = {
                             ^~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   In file included from drivers/net/ethernet/cavium/liquidio/lio_main.c:31:0:
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_unmap_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:97:3: error: implicit declaration of function 'pci_release_region'; did you mean 'pci_release_regions'? [-Werror=implicit-function-declaration]
      pci_release_region(oct->pci_dev, baridx * 2);
      ^~~~~~~~~~~~~~~~~~
      pci_release_regions
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_map_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:111:6: error: implicit declaration of function 'pci_request_region'; did you mean 'pci_request_regions'? [-Werror=implicit-function-declaration]
     if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) {
         ^~~~~~~~~~~~~~~~~~
         pci_request_regions
   drivers/net/ethernet/cavium/liquidio/lio_main.c: In function 'stop_pci_io':
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:332:3: error: implicit declaration of function 'pci_disable_msi'; did you mean 'pci_disable_sriov'? [-Werror=implicit-function-declaration]
      pci_disable_msi(oct->pci_dev);
      ^~~~~~~~~~~~~~~
      pci_disable_sriov
   drivers/net/ethernet/cavium/liquidio/lio_main.c: In function 'octeon_pci_flr':
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:983:2: error: implicit declaration of function 'pci_cfg_access_lock'; did you mean '__access_ok'? [-Werror=implicit-function-declaration]
     pci_cfg_access_lock(oct->pci_dev);
     ^~~~~~~~~~~~~~~~~~~
     __access_ok
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:989:7: error: implicit declaration of function '__pci_reset_function_locked' [-Werror=implicit-function-declaration]
     rc = __pci_reset_function_locked(oct->pci_dev);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:995:2: error: implicit declaration of function 'pci_cfg_access_unlock'; did you mean '__access_ok'? [-Werror=implicit-function-declaration]
     pci_cfg_access_unlock(oct->pci_dev);
     ^~~~~~~~~~~~~~~~~~~~~
     __access_ok
   drivers/net/ethernet/cavium/liquidio/lio_main.c: In function 'octeon_destroy_resources':
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:1063:20: error: invalid use of undefined type 'struct msix_entry'
           msix_entries[i].vector,
                       ^
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:1063:20: error: dereferencing pointer to incomplete type 'struct msix_entry'
   drivers/net/ethernet/cavium/liquidio/lio_main.c:1065:27: error: invalid use of undefined type 'struct msix_entry'
         free_irq(msix_entries[i].vector,
                              ^
   drivers/net/ethernet/cavium/liquidio/lio_main.c:1071:25: error: invalid use of undefined type 'struct msix_entry'
       free_irq(msix_entries[i].vector, oct);
                            ^
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:1073:4: error: implicit declaration of function 'pci_disable_msix'; did you mean 'pci_disable_sriov'? [-Werror=implicit-function-declaration]
       pci_disable_msix(oct->pci_dev);
       ^~~~~~~~~~~~~~~~
       pci_disable_sriov
>> drivers/net/ethernet/cavium/liquidio/lio_main.c:1164:3: error: implicit declaration of function 'pci_clear_master'; did you mean 'pci_set_master'? [-Werror=implicit-function-declaration]
      pci_clear_master(oct->pci_dev);
      ^~~~~~~~~~~~~~~~
      pci_set_master
   cc1: some warnings being treated as errors
--
   In file included from drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:26:0:
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_unmap_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:97:3: error: implicit declaration of function 'pci_release_region'; did you mean 'pci_release_regions'? [-Werror=implicit-function-declaration]
      pci_release_region(oct->pci_dev, baridx * 2);
      ^~~~~~~~~~~~~~~~~~
      pci_release_regions
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_map_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:111:6: error: implicit declaration of function 'pci_request_region'; did you mean 'pci_request_regions'? [-Werror=implicit-function-declaration]
     if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) {
         ^~~~~~~~~~~~~~~~~~
         pci_request_regions
   Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
   Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
   Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_read
   Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_write
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_read
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_set
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_dec_and_test
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_read
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_set
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_dec_and_test
   Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:set_bit
   Cyclomatic Complexity 2 arch/x86/include/asm/bitops.h:clear_bit
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:constant_test_bit
   Cyclomatic Complexity 1 arch/x86/include/uapi/asm/swab.h:__arch_swab32
   Cyclomatic Complexity 1 arch/x86/include/uapi/asm/swab.h:__arch_swab64
   Cyclomatic Complexity 1 include/uapi/linux/swab.h:__fswab32
   Cyclomatic Complexity 1 include/uapi/linux/swab.h:__fswab64
   Cyclomatic Complexity 2 include/uapi/linux/swab.h:__swab64p
   Cyclomatic Complexity 1 include/uapi/linux/swab.h:__swab64s
   Cyclomatic Complexity 1 include/linux/jump_label.h:static_key_count
   Cyclomatic Complexity 2 include/linux/jump_label.h:static_key_false
   Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
   Cyclomatic Complexity 1 arch/um/include/shared/mem.h:to_phys
   Cyclomatic Complexity 1 arch/um/include/shared/mem.h:to_virt
   Cyclomatic Complexity 1 include/linux/bottom_half.h:local_bh_disable
   Cyclomatic Complexity 1 include/linux/bottom_half.h:local_bh_enable
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock
   Cyclomatic Complexity 1 include/linux/jiffies.h:_msecs_to_jiffies
   Cyclomatic Complexity 3 include/linux/jiffies.h:msecs_to_jiffies
   Cyclomatic Complexity 1 include/linux/workqueue.h:queue_delayed_work
   Cyclomatic Complexity 1 include/linux/workqueue.h:schedule_delayed_work
   Cyclomatic Complexity 1 include/linux/completion.h:__init_completion
   Cyclomatic Complexity 2 include/linux/page-flags.h:compound_head
   Cyclomatic Complexity 1 include/linux/page_ref.h:page_ref_count
   Cyclomatic Complexity 2 include/linux/page_ref.h:page_ref_dec_and_test
   Cyclomatic Complexity 1 include/linux/mm.h:put_page_testzero
   Cyclomatic Complexity 1 include/linux/mm.h:put_devmap_managed_page
   Cyclomatic Complexity 3 include/linux/mm.h:put_page
   Cyclomatic Complexity 1 include/linux/mm.h:lowmem_page_address
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:valid_dma_direction
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:get_dma_ops
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:dma_map_single_attrs
   Cyclomatic Complexity 2 include/linux/dma-mapping.h:dma_unmap_single_attrs
   Cyclomatic Complexity 2 include/linux/dma-mapping.h:dma_mapping_error
   Cyclomatic Complexity 1 include/linux/skbuff.h:skb_end_pointer
   Cyclomatic Complexity 1 include/linux/skbuff.h:skb_copy_to_linear_data
   Cyclomatic Complexity 1 include/linux/netdevice.h:netdev_get_tx_queue
   Cyclomatic Complexity 1 include/linux/netdevice.h:netdev_priv
   Cyclomatic Complexity 1 include/linux/netdevice.h:netdev_notifier_info_to_dev
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_tx_start_queue
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_start_queue
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_wake_queue
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_tx_stop_queue
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_stop_queue
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_tx_queue_stopped
   Cyclomatic Complexity 1 include/linux/netdevice.h:netif_queue_stopped
   Cyclomatic Complexity 1 include/linux/netdevice.h:dev_kfree_skb_any
   Cyclomatic Complexity 1 include/linux/netdevice.h:__netif_tx_lock
   Cyclomatic Complexity 1 include/linux/netdevice.h:__netif_tx_unlock
   Cyclomatic Complexity 2 include/linux/netdevice.h:netif_trans_update
   Cyclomatic Complexity 2 include/linux/netdevice.h:netif_tx_disable
   Cyclomatic Complexity 1 include/linux/etherdevice.h:eth_random_addr
   Cyclomatic Complexity 1 include/linux/etherdevice.h:eth_hw_addr_random
   Cyclomatic Complexity 1 include/linux/etherdevice.h:ether_addr_copy
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/octeon_droq.h:octeon_free_recv_info
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/octeon_nic.h:octnet_iq_is_full
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/octeon_main.h:octeon_swap_8B_data
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/octeon_network.h:recv_buffer_free
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_tx_timeout
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_get_stats64
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_get_ndev
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_attr_get
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_copy_packet
   Cyclomatic Complexity 6 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_pkt_recv
   Cyclomatic Complexity 9 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_pkt_xmit
   Cyclomatic Complexity 6 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_send_soft_command
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_fetch_stats
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_stop
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_packet_sent_callback
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_send_sc_complete
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_change_mtu
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_phys_port_name
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_open
   Cyclomatic Complexity 5 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_netdev_event
   Cyclomatic Complexity 9 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_create
   Cyclomatic Complexity 5 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_destroy
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_modinit
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c:lio_vf_rep_modexit
   cc1: some warnings being treated as errors
--
   In file included from drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:27:0:
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_unmap_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:97:3: error: implicit declaration of function 'pci_release_region'; did you mean 'pci_release_regions'? [-Werror=implicit-function-declaration]
      pci_release_region(oct->pci_dev, baridx * 2);
      ^~~~~~~~~~~~~~~~~~
      pci_release_regions
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_map_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:111:6: error: implicit declaration of function 'pci_request_region'; did you mean 'pci_request_regions'? [-Werror=implicit-function-declaration]
     if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) {
         ^~~~~~~~~~~~~~~~~~
         pci_request_regions
   drivers/net/ethernet/cavium/liquidio/lio_ethtool.c: In function 'lio_irq_reallocate_irqs':
>> drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:562:39: error: invalid use of undefined type 'struct msix_entry'
        irq_set_affinity_hint(msix_entries[i].vector,
                                          ^
>> drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:562:39: error: dereferencing pointer to incomplete type 'struct msix_entry'
   drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:564:26: error: invalid use of undefined type 'struct msix_entry'
        free_irq(msix_entries[i].vector,
                             ^
   drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:572:25: error: invalid use of undefined type 'struct msix_entry'
       free_irq(msix_entries[i].vector, oct);
                            ^
>> drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:574:3: error: implicit declaration of function 'pci_disable_msix'; did you mean 'pci_disable_sriov'? [-Werror=implicit-function-declaration]
      pci_disable_msix(oct->pci_dev);
      ^~~~~~~~~~~~~~~~
      pci_disable_sriov
   cc1: some warnings being treated as errors
--
   In file included from drivers/net/ethernet/cavium/liquidio/lio_core.c:26:0:
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_unmap_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:97:3: error: implicit declaration of function 'pci_release_region'; did you mean 'pci_release_regions'? [-Werror=implicit-function-declaration]
      pci_release_region(oct->pci_dev, baridx * 2);
      ^~~~~~~~~~~~~~~~~~
      pci_release_regions
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_map_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:111:6: error: implicit declaration of function 'pci_request_region'; did you mean 'pci_request_regions'? [-Werror=implicit-function-declaration]
     if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) {
         ^~~~~~~~~~~~~~~~~~
         pci_request_regions
   drivers/net/ethernet/cavium/liquidio/lio_core.c: In function 'octeon_setup_interrupt':
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1067:17: error: invalid application of 'sizeof' to incomplete type 'struct msix_entry'
             sizeof(struct msix_entry),
                    ^~~~~~
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1083:17: error: invalid use of undefined type 'struct msix_entry'
        msix_entries[i].entry =
                    ^
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1083:17: error: dereferencing pointer to incomplete type 'struct msix_entry'
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1086:16: error: invalid use of undefined type 'struct msix_entry'
       msix_entries[oct->num_msix_irqs - 1].entry =
                   ^
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1086:4: error: invalid use of undefined type 'struct msix_entry'
       msix_entries[oct->num_msix_irqs - 1].entry =
       ^~~~~~~~~~~~
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1090:17: error: invalid use of undefined type 'struct msix_entry'
        msix_entries[i].entry = i;
                    ^
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1092:27: error: implicit declaration of function 'pci_enable_msix_range'; did you mean 'pci_enable_sriov'? [-Werror=implicit-function-declaration]
      num_alloc_ioq_vectors = pci_enable_msix_range(
                              ^~~~~~~~~~~~~~~~~~~~~
                              pci_enable_sriov
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1116:18: error: invalid use of undefined type 'struct msix_entry'
         msix_entries[num_ioq_vectors].vector,
                     ^
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1123:5: error: implicit declaration of function 'pci_disable_msix'; did you mean 'pci_disable_sriov'? [-Werror=implicit-function-declaration]
        pci_disable_msix(oct->pci_dev);
        ^~~~~~~~~~~~~~~~
        pci_disable_sriov
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1142:37: error: invalid use of undefined type 'struct msix_entry'
       irqret = request_irq(msix_entries[i].vector,
                                        ^
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1152:26: error: invalid use of undefined type 'struct msix_entry'
        free_irq(msix_entries[num_ioq_vectors].vector,
                             ^
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1159:25: error: invalid use of undefined type 'struct msix_entry'
                msix_entries[i].vector,
                            ^
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1161:27: error: invalid use of undefined type 'struct msix_entry'
         free_irq(msix_entries[i].vector,
                              ^
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1171:44: error: invalid use of undefined type 'struct msix_entry'
       oct->ioq_vector[i].vector = msix_entries[i].vector;
                                               ^
   drivers/net/ethernet/cavium/liquidio/lio_core.c:1173:38: error: invalid use of undefined type 'struct msix_entry'
       irq_set_affinity_hint(msix_entries[i].vector,
                                         ^
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1180:9: error: implicit declaration of function 'pci_enable_msi'; did you mean 'pci_enable_sriov'? [-Werror=implicit-function-declaration]
      err = pci_enable_msi(oct->pci_dev);
            ^~~~~~~~~~~~~~
            pci_enable_sriov
>> drivers/net/ethernet/cavium/liquidio/lio_core.c:1210:5: error: implicit declaration of function 'pci_disable_msi'; did you mean 'pci_disable_sriov'? [-Werror=implicit-function-declaration]
        pci_disable_msi(oct->pci_dev);
        ^~~~~~~~~~~~~~~
        pci_disable_sriov
   cc1: some warnings being treated as errors
--
   In file included from drivers/net/ethernet/cavium/liquidio/request_manager.c:27:0:
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_unmap_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:97:3: error: implicit declaration of function 'pci_release_region'; did you mean 'pci_release_regions'? [-Werror=implicit-function-declaration]
      pci_release_region(oct->pci_dev, baridx * 2);
      ^~~~~~~~~~~~~~~~~~
      pci_release_regions
   drivers/net/ethernet/cavium/liquidio/octeon_main.h: In function 'octeon_map_pci_barx':
>> drivers/net/ethernet/cavium/liquidio/octeon_main.h:111:6: error: implicit declaration of function 'pci_request_region'; did you mean 'pci_request_regions'? [-Werror=implicit-function-declaration]
     if (pci_request_region(oct->pci_dev, baridx * 2, DRV_NAME)) {
         ^~~~~~~~~~~~~~~~~~
         pci_request_regions
   Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
   Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
   Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_read
   Cyclomatic Complexity 1 include/linux/kasan-checks.h:kasan_check_write
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_read
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_set
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_sub
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_inc
   Cyclomatic Complexity 1 arch/x86/include/asm/atomic.h:arch_atomic_dec
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_read
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_set
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_inc
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_dec
   Cyclomatic Complexity 1 include/asm-generic/atomic-instrumented.h:atomic_sub
   Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
   Cyclomatic Complexity 2 include/linux/list.h:__list_add
   Cyclomatic Complexity 1 include/linux/list.h:list_add_tail
   Cyclomatic Complexity 1 include/linux/list.h:__list_del
   Cyclomatic Complexity 2 include/linux/list.h:__list_del_entry
   Cyclomatic Complexity 1 include/linux/list.h:list_del
   Cyclomatic Complexity 1 include/linux/list.h:list_empty
   Cyclomatic Complexity 1 arch/um/include/asm/irqflags.h:arch_local_save_flags
   Cyclomatic Complexity 1 include/asm-generic/irqflags.h:arch_irqs_disabled_flags
   Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock_bh
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_trylock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_bh
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_irqrestore
   Cyclomatic Complexity 1 include/linux/jiffies.h:_msecs_to_jiffies
   Cyclomatic Complexity 3 include/linux/jiffies.h:msecs_to_jiffies
   Cyclomatic Complexity 1 include/linux/workqueue.h:queue_delayed_work
   Cyclomatic Complexity 2 include/linux/overflow.h:array_size
   Cyclomatic Complexity 1 include/linux/device.h:dev_to_node
   Cyclomatic Complexity 1 include/asm-generic/io.h:__raw_writel
   Cyclomatic Complexity 1 include/asm-generic/io.h:writel
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:get_dma_ops
   Cyclomatic Complexity 7 include/linux/dma-mapping.h:dma_alloc_attrs
   Cyclomatic Complexity 4 include/linux/dma-mapping.h:dma_free_attrs
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:dma_alloc_coherent
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:dma_free_coherent
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/liquidio_common.h:incr_index
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/request_manager.c:ring_doorbell
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/request_manager.c:__copy_cmd_into_iq
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/request_manager.c:__post_command2
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/request_manager.c:__add_to_request_list
   Cyclomatic Complexity 10 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_init_instr_queue
   Cyclomatic Complexity 5 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_delete_instr_queue
   Cyclomatic Complexity 7 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_setup_iq
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_ring_doorbell_locked
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_register_reqtype_free_fn
   Cyclomatic Complexity 11 drivers/net/ethernet/cavium/liquidio/request_manager.c:lio_process_iq_request_list
   Cyclomatic Complexity 7 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_flush_iq
   Cyclomatic Complexity 7 drivers/net/ethernet/cavium/liquidio/request_manager.c:__check_db_timeout
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/request_manager.c:check_db_timeout
   Cyclomatic Complexity 8 drivers/net/ethernet/cavium/liquidio/request_manager.c:lio_wait_for_instr_fetch
   Cyclomatic Complexity 5 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_send_command
   Cyclomatic Complexity 8 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_prepare_soft_command
   Cyclomatic Complexity 13 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_send_soft_command
   Cyclomatic Complexity 2 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_free_sc_buffer_pool
   Cyclomatic Complexity 3 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_setup_sc_buffer_pool
   Cyclomatic Complexity 7 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_alloc_soft_command
   Cyclomatic Complexity 1 drivers/net/ethernet/cavium/liquidio/request_manager.c:octeon_free_soft_command
   cc1: some warnings being treated as errors
..

vim +40 drivers/net/phy/mdio-thunder.c

379d7ac7 David Daney 2016-03-11   24  
379d7ac7 David Daney 2016-03-11   25  static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
379d7ac7 David Daney 2016-03-11   26  				     const struct pci_device_id *ent)
379d7ac7 David Daney 2016-03-11   27  {
379d7ac7 David Daney 2016-03-11   28  	struct device_node *node;
379d7ac7 David Daney 2016-03-11   29  	struct fwnode_handle *fwn;
379d7ac7 David Daney 2016-03-11   30  	struct thunder_mdiobus_nexus *nexus;
379d7ac7 David Daney 2016-03-11   31  	int err;
379d7ac7 David Daney 2016-03-11   32  	int i;
379d7ac7 David Daney 2016-03-11   33  
379d7ac7 David Daney 2016-03-11   34  	nexus = devm_kzalloc(&pdev->dev, sizeof(*nexus), GFP_KERNEL);
379d7ac7 David Daney 2016-03-11   35  	if (!nexus)
379d7ac7 David Daney 2016-03-11   36  		return -ENOMEM;
379d7ac7 David Daney 2016-03-11   37  
379d7ac7 David Daney 2016-03-11   38  	pci_set_drvdata(pdev, nexus);
379d7ac7 David Daney 2016-03-11   39  
379d7ac7 David Daney 2016-03-11  @40  	err = pcim_enable_device(pdev);
379d7ac7 David Daney 2016-03-11   41  	if (err) {
379d7ac7 David Daney 2016-03-11   42  		dev_err(&pdev->dev, "Failed to enable PCI device\n");
379d7ac7 David Daney 2016-03-11   43  		pci_set_drvdata(pdev, NULL);
379d7ac7 David Daney 2016-03-11   44  		return err;
379d7ac7 David Daney 2016-03-11   45  	}
379d7ac7 David Daney 2016-03-11   46  
379d7ac7 David Daney 2016-03-11   47  	err = pci_request_regions(pdev, KBUILD_MODNAME);
379d7ac7 David Daney 2016-03-11   48  	if (err) {
379d7ac7 David Daney 2016-03-11   49  		dev_err(&pdev->dev, "pci_request_regions failed\n");
379d7ac7 David Daney 2016-03-11   50  		goto err_disable_device;
379d7ac7 David Daney 2016-03-11   51  	}
379d7ac7 David Daney 2016-03-11   52  
379d7ac7 David Daney 2016-03-11   53  	nexus->bar0 = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
379d7ac7 David Daney 2016-03-11   54  	if (!nexus->bar0) {
379d7ac7 David Daney 2016-03-11   55  		err = -ENOMEM;
379d7ac7 David Daney 2016-03-11   56  		goto err_release_regions;
379d7ac7 David Daney 2016-03-11   57  	}
379d7ac7 David Daney 2016-03-11   58  
379d7ac7 David Daney 2016-03-11   59  	i = 0;
379d7ac7 David Daney 2016-03-11   60  	device_for_each_child_node(&pdev->dev, fwn) {
379d7ac7 David Daney 2016-03-11   61  		struct resource r;
379d7ac7 David Daney 2016-03-11   62  		struct mii_bus *mii_bus;
379d7ac7 David Daney 2016-03-11   63  		struct cavium_mdiobus *bus;
379d7ac7 David Daney 2016-03-11   64  		union cvmx_smix_en smi_en;
379d7ac7 David Daney 2016-03-11   65  
379d7ac7 David Daney 2016-03-11   66  		/* If it is not an OF node we cannot handle it yet, so
379d7ac7 David Daney 2016-03-11   67  		 * exit the loop.
379d7ac7 David Daney 2016-03-11   68  		 */
379d7ac7 David Daney 2016-03-11   69  		node = to_of_node(fwn);
379d7ac7 David Daney 2016-03-11   70  		if (!node)
379d7ac7 David Daney 2016-03-11   71  			break;
379d7ac7 David Daney 2016-03-11   72  
379d7ac7 David Daney 2016-03-11   73  		err = of_address_to_resource(node, 0, &r);
379d7ac7 David Daney 2016-03-11   74  		if (err) {
379d7ac7 David Daney 2016-03-11   75  			dev_err(&pdev->dev,
379d7ac7 David Daney 2016-03-11   76  				"Couldn't translate address for \"%s\"\n",
379d7ac7 David Daney 2016-03-11   77  				node->name);
379d7ac7 David Daney 2016-03-11   78  			break;
379d7ac7 David Daney 2016-03-11   79  		}
379d7ac7 David Daney 2016-03-11   80  
379d7ac7 David Daney 2016-03-11   81  		mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus));
379d7ac7 David Daney 2016-03-11   82  		if (!mii_bus)
379d7ac7 David Daney 2016-03-11   83  			break;
379d7ac7 David Daney 2016-03-11   84  		bus = mii_bus->priv;
379d7ac7 David Daney 2016-03-11   85  		bus->mii_bus = mii_bus;
379d7ac7 David Daney 2016-03-11   86  
379d7ac7 David Daney 2016-03-11   87  		nexus->buses[i] = bus;
379d7ac7 David Daney 2016-03-11   88  		i++;
379d7ac7 David Daney 2016-03-11   89  
379d7ac7 David Daney 2016-03-11   90  		bus->register_base = (u64)nexus->bar0 +
379d7ac7 David Daney 2016-03-11   91  			r.start - pci_resource_start(pdev, 0);
379d7ac7 David Daney 2016-03-11   92  
379d7ac7 David Daney 2016-03-11   93  		smi_en.u64 = 0;
379d7ac7 David Daney 2016-03-11   94  		smi_en.s.en = 1;
379d7ac7 David Daney 2016-03-11   95  		oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
379d7ac7 David Daney 2016-03-11   96  		bus->mii_bus->name = KBUILD_MODNAME;
379d7ac7 David Daney 2016-03-11   97  		snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", r.start);
379d7ac7 David Daney 2016-03-11   98  		bus->mii_bus->parent = &pdev->dev;
379d7ac7 David Daney 2016-03-11   99  		bus->mii_bus->read = cavium_mdiobus_read;
379d7ac7 David Daney 2016-03-11  100  		bus->mii_bus->write = cavium_mdiobus_write;
379d7ac7 David Daney 2016-03-11  101  
379d7ac7 David Daney 2016-03-11  102  		err = of_mdiobus_register(bus->mii_bus, node);
379d7ac7 David Daney 2016-03-11  103  		if (err)
379d7ac7 David Daney 2016-03-11  104  			dev_err(&pdev->dev, "of_mdiobus_register failed\n");
379d7ac7 David Daney 2016-03-11  105  
379d7ac7 David Daney 2016-03-11  106  		dev_info(&pdev->dev, "Added bus at %llx\n", r.start);
379d7ac7 David Daney 2016-03-11  107  		if (i >= ARRAY_SIZE(nexus->buses))
379d7ac7 David Daney 2016-03-11  108  			break;
379d7ac7 David Daney 2016-03-11  109  	}
379d7ac7 David Daney 2016-03-11  110  	return 0;
379d7ac7 David Daney 2016-03-11  111  
379d7ac7 David Daney 2016-03-11  112  err_release_regions:
379d7ac7 David Daney 2016-03-11  113  	pci_release_regions(pdev);
379d7ac7 David Daney 2016-03-11  114  
379d7ac7 David Daney 2016-03-11  115  err_disable_device:
379d7ac7 David Daney 2016-03-11  116  	pci_set_drvdata(pdev, NULL);
379d7ac7 David Daney 2016-03-11  117  	return err;
379d7ac7 David Daney 2016-03-11  118  }
379d7ac7 David Daney 2016-03-11  119  
379d7ac7 David Daney 2016-03-11  120  static void thunder_mdiobus_pci_remove(struct pci_dev *pdev)
379d7ac7 David Daney 2016-03-11  121  {
379d7ac7 David Daney 2016-03-11  122  	int i;
379d7ac7 David Daney 2016-03-11  123  	struct thunder_mdiobus_nexus *nexus = pci_get_drvdata(pdev);
379d7ac7 David Daney 2016-03-11  124  
379d7ac7 David Daney 2016-03-11  125  	for (i = 0; i < ARRAY_SIZE(nexus->buses); i++) {
379d7ac7 David Daney 2016-03-11  126  		struct cavium_mdiobus *bus = nexus->buses[i];
379d7ac7 David Daney 2016-03-11  127  
379d7ac7 David Daney 2016-03-11  128  		if (!bus)
379d7ac7 David Daney 2016-03-11  129  			continue;
379d7ac7 David Daney 2016-03-11  130  
379d7ac7 David Daney 2016-03-11  131  		mdiobus_unregister(bus->mii_bus);
379d7ac7 David Daney 2016-03-11  132  		mdiobus_free(bus->mii_bus);
379d7ac7 David Daney 2016-03-11  133  		oct_mdio_writeq(0, bus->register_base + SMI_EN);
379d7ac7 David Daney 2016-03-11  134  	}
379d7ac7 David Daney 2016-03-11  135  	pci_set_drvdata(pdev, NULL);
379d7ac7 David Daney 2016-03-11  136  }
379d7ac7 David Daney 2016-03-11  137  
379d7ac7 David Daney 2016-03-11  138  static const struct pci_device_id thunder_mdiobus_id_table[] = {
379d7ac7 David Daney 2016-03-11  139  	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa02b) },
379d7ac7 David Daney 2016-03-11  140  	{ 0, } /* End of table. */
379d7ac7 David Daney 2016-03-11  141  };
379d7ac7 David Daney 2016-03-11  142  MODULE_DEVICE_TABLE(pci, thunder_mdiobus_id_table);
379d7ac7 David Daney 2016-03-11  143  
379d7ac7 David Daney 2016-03-11  144  static struct pci_driver thunder_mdiobus_driver = {
379d7ac7 David Daney 2016-03-11  145  	.name = KBUILD_MODNAME,
379d7ac7 David Daney 2016-03-11  146  	.id_table = thunder_mdiobus_id_table,
379d7ac7 David Daney 2016-03-11  147  	.probe = thunder_mdiobus_pci_probe,
379d7ac7 David Daney 2016-03-11  148  	.remove = thunder_mdiobus_pci_remove,
379d7ac7 David Daney 2016-03-11  149  };
379d7ac7 David Daney 2016-03-11  150  
379d7ac7 David Daney 2016-03-11 @151  module_pci_driver(thunder_mdiobus_driver);
379d7ac7 David Daney 2016-03-11  152  

:::::: The code at line 40 was first introduced by commit
:::::: 379d7ac7ca31722a1fb488ae3e98b274c9db568c phy: mdio-thunder: Add driver for Cavium Thunder SoC MDIO buses.

:::::: TO: David Daney <david.daney@cavium.com>
:::::: CC: David S. Miller <davem@davemloft.net>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 19891 bytes --]

^ permalink raw reply

* [PATCH bpf-next 0/9] bpf: offload program and map sharing
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski

Hi!

This patchset adds support for sharing BPF objects within one ASIC.
This will allow us to reuse of the same program on multiple ports of
a device leading to better code store utilization.  It also enables
sharing maps between programs attached to different ports of a device.

Jakub Kicinski (9):
  netdevsim: add switch_id attribute
  netdevsim: add shared netdevsim devices
  netdevsim: associate bound programs with shared dev
  nfp: add .ndo_init() and .ndo_uninit() callbacks
  bpf: offload: aggregate offloads per-device
  bpf: offload: allow program and map sharing per-ASIC
  netdevsim: allow program sharing between devices
  nfp: bpf: allow program sharing within ASIC
  selftests/bpf: add test for sharing objects between netdevs

 drivers/net/ethernet/netronome/nfp/bpf/main.c |  23 ++
 drivers/net/ethernet/netronome/nfp/bpf/main.h |   4 +
 .../net/ethernet/netronome/nfp/bpf/offload.c  |  10 +-
 drivers/net/ethernet/netronome/nfp/nfp_app.c  |  17 ++
 drivers/net/ethernet/netronome/nfp/nfp_app.h  |   8 +
 .../ethernet/netronome/nfp/nfp_net_common.c   |   2 +
 .../net/ethernet/netronome/nfp/nfp_net_repr.c |   2 +
 drivers/net/netdevsim/bpf.c                   |  50 +++-
 drivers/net/netdevsim/netdev.c                | 103 +++++++-
 drivers/net/netdevsim/netdevsim.h             |  23 +-
 include/linux/bpf.h                           |  10 +-
 kernel/bpf/offload.c                          | 223 ++++++++++++++----
 kernel/bpf/verifier.c                         |   2 +-
 tools/testing/selftests/bpf/test_offload.py   | 151 +++++++++++-
 14 files changed, 543 insertions(+), 85 deletions(-)

-- 
2.17.1

^ permalink raw reply

* [PATCH bpf-next 1/9] netdevsim: add switch_id attribute
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Grouping netdevsim devices into "ASICs" will soon be supported.
Add switch_id attribute to all netdevsims.  For now each netdevsim
will have its switch_id matching the device id.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/netdevsim/netdev.c    | 24 ++++++++++++++++++++++++
 drivers/net/netdevsim/netdevsim.h |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index a7b179f0d954..9125637ef5d8 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -22,6 +22,7 @@
 #include <net/netlink.h>
 #include <net/pkt_cls.h>
 #include <net/rtnetlink.h>
+#include <net/switchdev.h>
 
 #include "netdevsim.h"
 
@@ -144,12 +145,34 @@ static struct device_type nsim_dev_type = {
 	.release = nsim_dev_release,
 };
 
+static int
+nsim_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+{
+	struct netdevsim *ns = netdev_priv(dev);
+
+	switch (attr->id) {
+	case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
+		attr->u.ppid.id_len = sizeof(ns->switch_id);
+		memcpy(&attr->u.ppid.id, &ns->switch_id,
+		       attr->u.ppid.id_len);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static const struct switchdev_ops nsim_switchdev_ops = {
+	.switchdev_port_attr_get	= nsim_port_attr_get,
+};
+
 static int nsim_init(struct net_device *dev)
 {
 	struct netdevsim *ns = netdev_priv(dev);
 	int err;
 
 	ns->netdev = dev;
+	ns->switch_id = nsim_dev_id;
+
 	ns->ddir = debugfs_create_dir(netdev_name(dev), nsim_ddir);
 	if (IS_ERR_OR_NULL(ns->ddir))
 		return -ENOMEM;
@@ -166,6 +189,7 @@ static int nsim_init(struct net_device *dev)
 		goto err_bpf_uninit;
 
 	SET_NETDEV_DEV(dev, &ns->dev);
+	SWITCHDEV_SET_OPS(dev, &nsim_switchdev_ops);
 
 	err = nsim_devlink_setup(ns);
 	if (err)
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 0aeabbe81cc6..e2f232325259 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -59,6 +59,7 @@ struct netdevsim {
 	struct u64_stats_sync syncp;
 
 	struct device dev;
+	u32 switch_id;
 
 	struct dentry *ddir;
 
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 2/9] netdevsim: add shared netdevsim devices
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Factor out sharable netdevsim sub-object and use IFLA_LINK to link
netdevsims together at creation time.  Sharable object will have
its own DebugFS directory.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/netdevsim/netdev.c    | 87 ++++++++++++++++++++++++++++---
 drivers/net/netdevsim/netdevsim.h | 10 +++-
 2 files changed, 90 insertions(+), 7 deletions(-)

diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 9125637ef5d8..2d244551298b 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -152,8 +152,8 @@ nsim_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
 
 	switch (attr->id) {
 	case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
-		attr->u.ppid.id_len = sizeof(ns->switch_id);
-		memcpy(&attr->u.ppid.id, &ns->switch_id,
+		attr->u.ppid.id_len = sizeof(ns->sdev->switch_id);
+		memcpy(&attr->u.ppid.id, &ns->sdev->switch_id,
 		       attr->u.ppid.id_len);
 		return 0;
 	default:
@@ -167,19 +167,41 @@ static const struct switchdev_ops nsim_switchdev_ops = {
 
 static int nsim_init(struct net_device *dev)
 {
+	char sdev_ddir_name[10], sdev_link_name[32];
 	struct netdevsim *ns = netdev_priv(dev);
 	int err;
 
 	ns->netdev = dev;
-	ns->switch_id = nsim_dev_id;
-
 	ns->ddir = debugfs_create_dir(netdev_name(dev), nsim_ddir);
 	if (IS_ERR_OR_NULL(ns->ddir))
 		return -ENOMEM;
 
+	if (!ns->sdev) {
+		ns->sdev = kzalloc(sizeof(*ns->sdev), GFP_KERNEL);
+		if (!ns->sdev) {
+			err = -ENOMEM;
+			goto err_debugfs_destroy;
+		}
+		ns->sdev->refcnt = 1;
+		ns->sdev->switch_id = nsim_dev_id;
+		sprintf(sdev_ddir_name, "%u", ns->sdev->switch_id);
+		ns->sdev->ddir = debugfs_create_dir(sdev_ddir_name,
+						    nsim_sdev_ddir);
+		if (IS_ERR_OR_NULL(ns->sdev->ddir)) {
+			err = PTR_ERR_OR_ZERO(ns->sdev->ddir) ?: -EINVAL;
+			goto err_sdev_free;
+		}
+	} else {
+		sprintf(sdev_ddir_name, "%u", ns->sdev->switch_id);
+		ns->sdev->refcnt++;
+	}
+
+	sprintf(sdev_link_name, "../../" DRV_NAME "_sdev/%s", sdev_ddir_name);
+	debugfs_create_symlink("sdev", ns->ddir, sdev_link_name);
+
 	err = nsim_bpf_init(ns);
 	if (err)
-		goto err_debugfs_destroy;
+		goto err_sdev_destroy;
 
 	ns->dev.id = nsim_dev_id++;
 	ns->dev.bus = &nsim_bus;
@@ -203,6 +225,12 @@ static int nsim_init(struct net_device *dev)
 	device_unregister(&ns->dev);
 err_bpf_uninit:
 	nsim_bpf_uninit(ns);
+err_sdev_destroy:
+	if (!--ns->sdev->refcnt) {
+		debugfs_remove_recursive(ns->sdev->ddir);
+err_sdev_free:
+		kfree(ns->sdev);
+	}
 err_debugfs_destroy:
 	debugfs_remove_recursive(ns->ddir);
 	return err;
@@ -216,6 +244,10 @@ static void nsim_uninit(struct net_device *dev)
 	nsim_devlink_teardown(ns);
 	debugfs_remove_recursive(ns->ddir);
 	nsim_bpf_uninit(ns);
+	if (!--ns->sdev->refcnt) {
+		debugfs_remove_recursive(ns->sdev->ddir);
+		kfree(ns->sdev);
+	}
 }
 
 static void nsim_free(struct net_device *dev)
@@ -494,14 +526,48 @@ static int nsim_validate(struct nlattr *tb[], struct nlattr *data[],
 	return 0;
 }
 
+static int nsim_newlink(struct net *src_net, struct net_device *dev,
+			struct nlattr *tb[], struct nlattr *data[],
+			struct netlink_ext_ack *extack)
+{
+	struct netdevsim *ns = netdev_priv(dev);
+
+	if (tb[IFLA_LINK]) {
+		struct net_device *joindev;
+		struct netdevsim *joinns;
+
+		joindev = __dev_get_by_index(src_net,
+					     nla_get_u32(tb[IFLA_LINK]));
+		if (!joindev)
+			return -ENODEV;
+		if (joindev->netdev_ops != &nsim_netdev_ops)
+			return -EINVAL;
+
+		joinns = netdev_priv(joindev);
+		if (!joinns->sdev || !joinns->sdev->refcnt)
+			return -EINVAL;
+		ns->sdev = joinns->sdev;
+	}
+
+	return register_netdevice(dev);
+}
+
+static void nsim_dellink(struct net_device *dev, struct list_head *head)
+{
+	unregister_netdevice_queue(dev, head);
+}
+
 static struct rtnl_link_ops nsim_link_ops __read_mostly = {
 	.kind		= DRV_NAME,
 	.priv_size	= sizeof(struct netdevsim),
 	.setup		= nsim_setup,
 	.validate	= nsim_validate,
+	.newlink	= nsim_newlink,
+	.dellink	= nsim_dellink,
 };
 
 struct dentry *nsim_ddir;
+struct dentry *nsim_sdev_ddir;
 
 static int __init nsim_module_init(void)
 {
@@ -511,9 +577,15 @@ static int __init nsim_module_init(void)
 	if (IS_ERR_OR_NULL(nsim_ddir))
 		return -ENOMEM;
 
+	nsim_sdev_ddir = debugfs_create_dir(DRV_NAME "_sdev", NULL);
+	if (IS_ERR_OR_NULL(nsim_sdev_ddir)) {
+		err = -ENOMEM;
+		goto err_debugfs_destroy;
+	}
+
 	err = bus_register(&nsim_bus);
 	if (err)
-		goto err_debugfs_destroy;
+		goto err_sdir_destroy;
 
 	err = nsim_devlink_init();
 	if (err)
@@ -529,6 +601,8 @@ static int __init nsim_module_init(void)
 	nsim_devlink_exit();
 err_unreg_bus:
 	bus_unregister(&nsim_bus);
+err_sdir_destroy:
+	debugfs_remove_recursive(nsim_sdev_ddir);
 err_debugfs_destroy:
 	debugfs_remove_recursive(nsim_ddir);
 	return err;
@@ -539,6 +613,7 @@ static void __exit nsim_module_exit(void)
 	rtnl_link_unregister(&nsim_link_ops);
 	nsim_devlink_exit();
 	bus_unregister(&nsim_bus);
+	debugfs_remove_recursive(nsim_sdev_ddir);
 	debugfs_remove_recursive(nsim_ddir);
 }
 
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index e2f232325259..8743ce74d2d9 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -30,6 +30,13 @@ struct bpf_prog;
 struct dentry;
 struct nsim_vf_config;
 
+struct netdevsim_shared_dev {
+	unsigned int refcnt;
+	u32 switch_id;
+
+	struct dentry *ddir;
+};
+
 #define NSIM_IPSEC_MAX_SA_COUNT		33
 #define NSIM_IPSEC_VALID		BIT(31)
 
@@ -59,7 +66,7 @@ struct netdevsim {
 	struct u64_stats_sync syncp;
 
 	struct device dev;
-	u32 switch_id;
+	struct netdevsim_shared_dev *sdev;
 
 	struct dentry *ddir;
 
@@ -93,6 +100,7 @@ struct netdevsim {
 };
 
 extern struct dentry *nsim_ddir;
+extern struct dentry *nsim_sdev_ddir;
 
 #ifdef CONFIG_BPF_SYSCALL
 int nsim_bpf_init(struct netdevsim *ns);
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 3/9] netdevsim: associate bound programs with shared dev
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Move bound program information from netdevsim to shared sub-object,
as programs will soon be shared between netdevs of the same ASIC.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/netdevsim/bpf.c                 | 30 ++++++++++++---------
 drivers/net/netdevsim/netdevsim.h           | 11 ++++----
 tools/testing/selftests/bpf/test_offload.py |  5 ++--
 3 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index c36d2a768202..357f9e62f306 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -238,8 +238,8 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)
 	state->state = "verify";
 
 	/* Program id is not populated yet when we create the state. */
-	sprintf(name, "%u", ns->prog_id_gen++);
-	state->ddir = debugfs_create_dir(name, ns->ddir_bpf_bound_progs);
+	sprintf(name, "%u", ns->sdev->prog_id_gen++);
+	state->ddir = debugfs_create_dir(name, ns->sdev->ddir_bpf_bound_progs);
 	if (IS_ERR_OR_NULL(state->ddir)) {
 		kfree(state);
 		return -ENOMEM;
@@ -250,7 +250,7 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)
 			    &state->state, &nsim_bpf_string_fops);
 	debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded);
 
-	list_add_tail(&state->l, &ns->bpf_bound_progs);
+	list_add_tail(&state->l, &ns->sdev->bpf_bound_progs);
 
 	prog->aux->offload->dev_priv = state;
 
@@ -497,7 +497,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap)
 	}
 
 	offmap->dev_ops = &nsim_bpf_map_ops;
-	list_add_tail(&nmap->l, &ns->bpf_bound_maps);
+	list_add_tail(&nmap->l, &ns->sdev->bpf_bound_maps);
 
 	return 0;
 
@@ -582,8 +582,15 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
 
 int nsim_bpf_init(struct netdevsim *ns)
 {
-	INIT_LIST_HEAD(&ns->bpf_bound_progs);
-	INIT_LIST_HEAD(&ns->bpf_bound_maps);
+	if (ns->sdev->refcnt == 1) {
+		INIT_LIST_HEAD(&ns->sdev->bpf_bound_progs);
+		INIT_LIST_HEAD(&ns->sdev->bpf_bound_maps);
+
+		ns->sdev->ddir_bpf_bound_progs =
+			debugfs_create_dir("bpf_bound_progs", ns->sdev->ddir);
+		if (IS_ERR_OR_NULL(ns->sdev->ddir_bpf_bound_progs))
+			return -ENOMEM;
+	}
 
 	debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir,
 			   &ns->bpf_offloaded_id);
@@ -593,10 +600,6 @@ int nsim_bpf_init(struct netdevsim *ns)
 			    &ns->bpf_bind_accept);
 	debugfs_create_u32("bpf_bind_verifier_delay", 0600, ns->ddir,
 			   &ns->bpf_bind_verifier_delay);
-	ns->ddir_bpf_bound_progs =
-		debugfs_create_dir("bpf_bound_progs", ns->ddir);
-	if (IS_ERR_OR_NULL(ns->ddir_bpf_bound_progs))
-		return -ENOMEM;
 
 	ns->bpf_tc_accept = true;
 	debugfs_create_bool("bpf_tc_accept", 0600, ns->ddir,
@@ -619,9 +622,12 @@ int nsim_bpf_init(struct netdevsim *ns)
 
 void nsim_bpf_uninit(struct netdevsim *ns)
 {
-	WARN_ON(!list_empty(&ns->bpf_bound_progs));
-	WARN_ON(!list_empty(&ns->bpf_bound_maps));
 	WARN_ON(ns->xdp.prog);
 	WARN_ON(ns->xdp_hw.prog);
 	WARN_ON(ns->bpf_offloaded);
+
+	if (ns->sdev->refcnt == 1) {
+		WARN_ON(!list_empty(&ns->sdev->bpf_bound_progs));
+		WARN_ON(!list_empty(&ns->sdev->bpf_bound_maps));
+	}
 }
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 8743ce74d2d9..98f26fa1e671 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -35,6 +35,12 @@ struct netdevsim_shared_dev {
 	u32 switch_id;
 
 	struct dentry *ddir;
+
+	struct dentry *ddir_bpf_bound_progs;
+	u32 prog_id_gen;
+
+	struct list_head bpf_bound_progs;
+	struct list_head bpf_bound_maps;
 };
 
 #define NSIM_IPSEC_MAX_SA_COUNT		33
@@ -79,12 +85,8 @@ struct netdevsim {
 	struct xdp_attachment_info xdp;
 	struct xdp_attachment_info xdp_hw;
 
-	u32 prog_id_gen;
-
 	bool bpf_bind_accept;
 	u32 bpf_bind_verifier_delay;
-	struct dentry *ddir_bpf_bound_progs;
-	struct list_head bpf_bound_progs;
 
 	bool bpf_tc_accept;
 	bool bpf_tc_non_bound_accept;
@@ -92,7 +94,6 @@ struct netdevsim {
 	bool bpf_xdpoffload_accept;
 
 	bool bpf_map_accept;
-	struct list_head bpf_bound_maps;
 #if IS_ENABLED(CONFIG_NET_DEVLINK)
 	struct devlink *devlink;
 #endif
diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py
index b746227eaff2..ee1abef384ea 100755
--- a/tools/testing/selftests/bpf/test_offload.py
+++ b/tools/testing/selftests/bpf/test_offload.py
@@ -314,6 +314,7 @@ netns = [] # net namespaces to be removed
         self.ns = ""
 
         self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname'])
+        self.sdev_dir = self.dfs_dir + '/sdev/'
         self.dfs_refresh()
 
     def __getitem__(self, key):
@@ -345,12 +346,12 @@ netns = [] # net namespaces to be removed
         return data.strip()
 
     def dfs_num_bound_progs(self):
-        path = os.path.join(self.dfs_dir, "bpf_bound_progs")
+        path = os.path.join(self.sdev_dir, "bpf_bound_progs")
         _, progs = cmd('ls %s' % (path))
         return len(progs.split())
 
     def dfs_get_bound_progs(self, expected):
-        progs = DebugfsDir(os.path.join(self.dfs_dir, "bpf_bound_progs"))
+        progs = DebugfsDir(os.path.join(self.sdev_dir, "bpf_bound_progs"))
         if expected is not None:
             if len(progs) != expected:
                 fail(True, "%d BPF programs bound, expected %d" %
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 4/9] nfp: add .ndo_init() and .ndo_uninit() callbacks
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

BPF code should unregister the offload capabilities from .ndo_uninit(),
to make sure the operation is atomic with unlist_netdevice().  Plumb
the init/uninit NDOs for vNICs and representors.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_app.c    | 17 +++++++++++++++++
 drivers/net/ethernet/netronome/nfp/nfp_app.h    |  8 ++++++++
 .../net/ethernet/netronome/nfp/nfp_net_common.c |  2 ++
 .../net/ethernet/netronome/nfp/nfp_net_repr.c   |  2 ++
 4 files changed, 29 insertions(+)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c
index f28b244f4ee7..69d4ae7a61f3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c
@@ -86,6 +86,23 @@ const char *nfp_app_mip_name(struct nfp_app *app)
 	return nfp_mip_name(app->pf->mip);
 }
 
+int nfp_app_ndo_init(struct net_device *netdev)
+{
+	struct nfp_app *app = nfp_app_from_netdev(netdev);
+
+	if (!app || !app->type->ndo_init)
+		return 0;
+	return app->type->ndo_init(app, netdev);
+}
+
+void nfp_app_ndo_uninit(struct net_device *netdev)
+{
+	struct nfp_app *app = nfp_app_from_netdev(netdev);
+
+	if (app && app->type->ndo_uninit)
+		app->type->ndo_uninit(app, netdev);
+}
+
 u64 *nfp_app_port_get_stats(struct nfp_port *port, u64 *data)
 {
 	if (!port || !port->app || !port->app->type->port_get_stats)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index ee74caacb015..afbc19aa66a8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -78,6 +78,8 @@ extern const struct nfp_app_type app_abm;
  * @init:	perform basic app checks and init
  * @clean:	clean app state
  * @extra_cap:	extra capabilities string
+ * @ndo_init:	vNIC and repr netdev .ndo_init
+ * @ndo_uninit:	vNIC and repr netdev .ndo_unint
  * @vnic_alloc:	allocate vNICs (assign port types, etc.)
  * @vnic_free:	free up app's vNIC state
  * @vnic_init:	vNIC netdev was registered
@@ -117,6 +119,9 @@ struct nfp_app_type {
 
 	const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn);
 
+	int (*ndo_init)(struct nfp_app *app, struct net_device *netdev);
+	void (*ndo_uninit)(struct nfp_app *app, struct net_device *netdev);
+
 	int (*vnic_alloc)(struct nfp_app *app, struct nfp_net *nn,
 			  unsigned int id);
 	void (*vnic_free)(struct nfp_app *app, struct nfp_net *nn);
@@ -200,6 +205,9 @@ static inline void nfp_app_clean(struct nfp_app *app)
 		app->type->clean(app);
 }
 
+int nfp_app_ndo_init(struct net_device *netdev);
+void nfp_app_ndo_uninit(struct net_device *netdev);
+
 static inline int nfp_app_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
 				     unsigned int id)
 {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index a712e83c3f0f..279b8ab8a17b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3480,6 +3480,8 @@ static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)
 }
 
 const struct net_device_ops nfp_net_netdev_ops = {
+	.ndo_init		= nfp_app_ndo_init,
+	.ndo_uninit		= nfp_app_ndo_uninit,
 	.ndo_open		= nfp_net_netdev_open,
 	.ndo_stop		= nfp_net_netdev_close,
 	.ndo_start_xmit		= nfp_net_tx,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index d7b712f6362f..18a09cdcd9c6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -262,6 +262,8 @@ static int nfp_repr_open(struct net_device *netdev)
 }
 
 const struct net_device_ops nfp_repr_netdev_ops = {
+	.ndo_init		= nfp_app_ndo_init,
+	.ndo_uninit		= nfp_app_ndo_uninit,
 	.ndo_open		= nfp_repr_open,
 	.ndo_stop		= nfp_repr_stop,
 	.ndo_start_xmit		= nfp_repr_xmit,
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 5/9] bpf: offload: aggregate offloads per-device
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Currently we have two lists of offloaded objects - programs and maps.
Netdevice unregister notifier scans those lists to orphan objects
associated with device being unregistered.  This puts unnecessary
(even if negligible) burden on all netdev unregister calls in BPF-
-enabled kernel.  The lists of objects may potentially get long
making the linear scan even more problematic.  There haven't been
complaints about this mechanisms so far, but it is suboptimal.

Instead of relying on notifiers, make the few BPF-capable drivers
register explicitly for BPF offloads.  The programs and maps will
now be collected per-device not on a global list, and only scanned
for removal when driver unregisters from BPF offloads.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/bpf/main.c |  13 ++
 drivers/net/netdevsim/bpf.c                   |   7 +
 include/linux/bpf.h                           |   2 +
 kernel/bpf/offload.c                          | 142 ++++++++++++------
 4 files changed, 118 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index b95b94d008cf..dee039ada75c 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -404,6 +404,16 @@ static int nfp_bpf_parse_capabilities(struct nfp_app *app)
 	return -EINVAL;
 }
 
+static int nfp_bpf_ndo_init(struct nfp_app *app, struct net_device *netdev)
+{
+	return bpf_offload_dev_netdev_register(netdev);
+}
+
+static void nfp_bpf_ndo_uninit(struct nfp_app *app, struct net_device *netdev)
+{
+	bpf_offload_dev_netdev_unregister(netdev);
+}
+
 static int nfp_bpf_init(struct nfp_app *app)
 {
 	struct nfp_app_bpf *bpf;
@@ -466,6 +476,9 @@ const struct nfp_app_type app_bpf = {
 
 	.extra_cap	= nfp_bpf_extra_cap,
 
+	.ndo_init	= nfp_bpf_ndo_init,
+	.ndo_uninit	= nfp_bpf_ndo_uninit,
+
 	.vnic_alloc	= nfp_bpf_vnic_alloc,
 	.vnic_free	= nfp_bpf_vnic_free,
 
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index 357f9e62f306..c4a2829e0e1f 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -582,6 +582,8 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
 
 int nsim_bpf_init(struct netdevsim *ns)
 {
+	int err;
+
 	if (ns->sdev->refcnt == 1) {
 		INIT_LIST_HEAD(&ns->sdev->bpf_bound_progs);
 		INIT_LIST_HEAD(&ns->sdev->bpf_bound_maps);
@@ -592,6 +594,10 @@ int nsim_bpf_init(struct netdevsim *ns)
 			return -ENOMEM;
 	}
 
+	err = bpf_offload_dev_netdev_register(ns->netdev);
+	if (err)
+		return err;
+
 	debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir,
 			   &ns->bpf_offloaded_id);
 
@@ -625,6 +631,7 @@ void nsim_bpf_uninit(struct netdevsim *ns)
 	WARN_ON(ns->xdp.prog);
 	WARN_ON(ns->xdp_hw.prog);
 	WARN_ON(ns->bpf_offloaded);
+	bpf_offload_dev_netdev_unregister(ns->netdev);
 
 	if (ns->sdev->refcnt == 1) {
 		WARN_ON(!list_empty(&ns->sdev->bpf_bound_progs));
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 8827e797ff97..21c001c3285c 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -648,6 +648,8 @@ int bpf_map_offload_delete_elem(struct bpf_map *map, void *key);
 int bpf_map_offload_get_next_key(struct bpf_map *map,
 				 void *key, void *next_key);
 
+int bpf_offload_dev_netdev_register(struct net_device *netdev);
+void bpf_offload_dev_netdev_unregister(struct net_device *netdev);
 bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map);
 
 #if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c
index ac747d5cf7c6..b914f94c53d4 100644
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@ -18,19 +18,37 @@
 #include <linux/bug.h>
 #include <linux/kdev_t.h>
 #include <linux/list.h>
+#include <linux/lockdep.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
 #include <linux/proc_ns.h>
+#include <linux/rhashtable.h>
 #include <linux/rtnetlink.h>
 #include <linux/rwsem.h>
 
-/* Protects bpf_prog_offload_devs, bpf_map_offload_devs and offload members
+/* Protects offdevs, members of bpf_offload_netdev and offload members
  * of all progs.
  * RTNL lock cannot be taken when holding this lock.
  */
 static DECLARE_RWSEM(bpf_devs_lock);
-static LIST_HEAD(bpf_prog_offload_devs);
-static LIST_HEAD(bpf_map_offload_devs);
+
+struct bpf_offload_netdev {
+	struct rhash_head l;
+	struct net_device *netdev;
+	struct list_head progs;
+	struct list_head maps;
+};
+
+static const struct rhashtable_params offdevs_params = {
+	.nelem_hint		= 4,
+	.key_len		= sizeof(struct net_device *),
+	.key_offset		= offsetof(struct bpf_offload_netdev, netdev),
+	.head_offset		= offsetof(struct bpf_offload_netdev, l),
+	.automatic_shrinking	= true,
+};
+
+static struct rhashtable offdevs;
+static bool offdevs_inited;
 
 static int bpf_dev_offload_check(struct net_device *netdev)
 {
@@ -41,8 +59,19 @@ static int bpf_dev_offload_check(struct net_device *netdev)
 	return 0;
 }
 
+static struct bpf_offload_netdev *
+bpf_offload_find_netdev(struct net_device *netdev)
+{
+	lockdep_assert_held(&bpf_devs_lock);
+
+	if (!offdevs_inited)
+		return NULL;
+	return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
+}
+
 int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
 {
+	struct bpf_offload_netdev *ondev;
 	struct bpf_prog_offload *offload;
 	int err;
 
@@ -66,12 +95,13 @@ int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
 		goto err_maybe_put;
 
 	down_write(&bpf_devs_lock);
-	if (offload->netdev->reg_state != NETREG_REGISTERED) {
+	ondev = bpf_offload_find_netdev(offload->netdev);
+	if (!ondev) {
 		err = -EINVAL;
 		goto err_unlock;
 	}
 	prog->aux->offload = offload;
-	list_add_tail(&offload->offloads, &bpf_prog_offload_devs);
+	list_add_tail(&offload->offloads, &ondev->progs);
 	dev_put(offload->netdev);
 	up_write(&bpf_devs_lock);
 
@@ -294,6 +324,7 @@ static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap,
 struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
 {
 	struct net *net = current->nsproxy->net_ns;
+	struct bpf_offload_netdev *ondev;
 	struct bpf_offloaded_map *offmap;
 	int err;
 
@@ -316,11 +347,17 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
 	if (err)
 		goto err_unlock;
 
+	ondev = bpf_offload_find_netdev(offmap->netdev);
+	if (!ondev) {
+		err = -EINVAL;
+		goto err_unlock;
+	}
+
 	err = bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_ALLOC);
 	if (err)
 		goto err_unlock;
 
-	list_add_tail(&offmap->offloads, &bpf_map_offload_devs);
+	list_add_tail(&offmap->offloads, &ondev->maps);
 	up_write(&bpf_devs_lock);
 	rtnl_unlock();
 
@@ -489,56 +526,69 @@ bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map)
 	return ret;
 }
 
-static void bpf_offload_orphan_all_progs(struct net_device *netdev)
+int bpf_offload_dev_netdev_register(struct net_device *netdev)
 {
-	struct bpf_prog_offload *offload, *tmp;
+	struct bpf_offload_netdev *ondev;
+	int err;
 
-	list_for_each_entry_safe(offload, tmp, &bpf_prog_offload_devs, offloads)
-		if (offload->netdev == netdev)
-			__bpf_prog_offload_destroy(offload->prog);
-}
+	down_write(&bpf_devs_lock);
+	if (!offdevs_inited) {
+		err = rhashtable_init(&offdevs, &offdevs_params);
+		if (err)
+			return err;
+		offdevs_inited = true;
+	}
+	up_write(&bpf_devs_lock);
 
-static void bpf_offload_orphan_all_maps(struct net_device *netdev)
-{
-	struct bpf_offloaded_map *offmap, *tmp;
+	ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
+	if (!ondev)
+		return -ENOMEM;
+
+	ondev->netdev = netdev;
+	INIT_LIST_HEAD(&ondev->progs);
+	INIT_LIST_HEAD(&ondev->maps);
+
+	down_write(&bpf_devs_lock);
+	err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params);
+	if (err) {
+		netdev_warn(netdev, "failed to register for BPF offload\n");
+		goto err_unlock_free;
+	}
 
-	list_for_each_entry_safe(offmap, tmp, &bpf_map_offload_devs, offloads)
-		if (offmap->netdev == netdev)
-			__bpf_map_offload_destroy(offmap);
+	up_write(&bpf_devs_lock);
+	return 0;
+
+err_unlock_free:
+	up_write(&bpf_devs_lock);
+	kfree(ondev);
+	return err;
 }
+EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_register);
 
-static int bpf_offload_notification(struct notifier_block *notifier,
-				    ulong event, void *ptr)
+void bpf_offload_dev_netdev_unregister(struct net_device *netdev)
 {
-	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
+	struct bpf_offloaded_map *offmap, *mtmp;
+	struct bpf_prog_offload *offload, *ptmp;
+	struct bpf_offload_netdev *ondev;
 
 	ASSERT_RTNL();
 
-	switch (event) {
-	case NETDEV_UNREGISTER:
-		/* ignore namespace changes */
-		if (netdev->reg_state != NETREG_UNREGISTERING)
-			break;
-
-		down_write(&bpf_devs_lock);
-		bpf_offload_orphan_all_progs(netdev);
-		bpf_offload_orphan_all_maps(netdev);
-		up_write(&bpf_devs_lock);
-		break;
-	default:
-		break;
-	}
-	return NOTIFY_OK;
-}
+	down_write(&bpf_devs_lock);
+	ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
+	if (WARN_ON(!ondev))
+		goto unlock;
 
-static struct notifier_block bpf_offload_notifier = {
-	.notifier_call = bpf_offload_notification,
-};
+	WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
 
-static int __init bpf_offload_init(void)
-{
-	register_netdevice_notifier(&bpf_offload_notifier);
-	return 0;
-}
+	list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
+		__bpf_prog_offload_destroy(offload->prog);
+	list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
+		__bpf_map_offload_destroy(offmap);
 
-subsys_initcall(bpf_offload_init);
+	WARN_ON(!list_empty(&ondev->progs));
+	WARN_ON(!list_empty(&ondev->maps));
+	kfree(ondev);
+unlock:
+	up_write(&bpf_devs_lock);
+}
+EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_unregister);
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 7/9] netdevsim: allow program sharing between devices
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Allow program sharing between devices which were linked together.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/netdevsim/bpf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index 9eab29f67a0e..81444208b216 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -294,7 +294,7 @@ nsim_setup_prog_hw_checks(struct netdevsim *ns, struct netdev_bpf *bpf)
 		NSIM_EA(bpf->extack, "xdpoffload of non-bound program");
 		return -EINVAL;
 	}
-	if (bpf->prog->aux->offload->netdev != ns->netdev) {
+	if (!bpf_offload_dev_match(bpf->prog, ns->netdev)) {
 		NSIM_EA(bpf->extack, "program bound to different dev");
 		return -EINVAL;
 	}
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 6/9] bpf: offload: allow program and map sharing per-ASIC
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Create a higher-level entity to represent a device/ASIC to allow
programs and maps to be shared between device ports.  The extra
work is required to make sure we don't destroy BPF objects as
soon as the netdev for which they were loaded gets destroyed,
as other ports may still be using them.  When netdev goes away
all of its BPF objects will be moved to other netdevs of the
device, and only destroyed when last netdev is unregistered.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/bpf/main.c |  14 +-
 drivers/net/ethernet/netronome/nfp/bpf/main.h |   4 +
 drivers/net/netdevsim/bpf.c                   |  17 ++-
 drivers/net/netdevsim/netdevsim.h             |   3 +
 include/linux/bpf.h                           |  12 +-
 kernel/bpf/offload.c                          | 123 ++++++++++++++----
 kernel/bpf/verifier.c                         |   2 +-
 7 files changed, 142 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index dee039ada75c..458f49235d06 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -406,12 +406,16 @@ static int nfp_bpf_parse_capabilities(struct nfp_app *app)
 
 static int nfp_bpf_ndo_init(struct nfp_app *app, struct net_device *netdev)
 {
-	return bpf_offload_dev_netdev_register(netdev);
+	struct nfp_app_bpf *bpf = app->priv;
+
+	return bpf_offload_dev_netdev_register(bpf->bpf_dev, netdev);
 }
 
 static void nfp_bpf_ndo_uninit(struct nfp_app *app, struct net_device *netdev)
 {
-	bpf_offload_dev_netdev_unregister(netdev);
+	struct nfp_app_bpf *bpf = app->priv;
+
+	bpf_offload_dev_netdev_unregister(bpf->bpf_dev, netdev);
 }
 
 static int nfp_bpf_init(struct nfp_app *app)
@@ -437,6 +441,11 @@ static int nfp_bpf_init(struct nfp_app *app)
 	if (err)
 		goto err_free_neutral_maps;
 
+	bpf->bpf_dev = bpf_offload_dev_create();
+	err = PTR_ERR_OR_ZERO(bpf->bpf_dev);
+	if (err)
+		goto err_free_neutral_maps;
+
 	return 0;
 
 err_free_neutral_maps:
@@ -455,6 +464,7 @@ static void nfp_bpf_clean(struct nfp_app *app)
 {
 	struct nfp_app_bpf *bpf = app->priv;
 
+	bpf_offload_dev_destroy(bpf->bpf_dev);
 	WARN_ON(!skb_queue_empty(&bpf->cmsg_replies));
 	WARN_ON(!list_empty(&bpf->map_list));
 	WARN_ON(bpf->maps_in_use || bpf->map_elems_in_use);
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h
index 9845c1a2d4c2..bec935468f90 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -110,6 +110,8 @@ enum pkt_vec {
  * struct nfp_app_bpf - bpf app priv structure
  * @app:		backpointer to the app
  *
+ * @bpf_dev:		BPF offload device handle
+ *
  * @tag_allocator:	bitmap of control message tags in use
  * @tag_alloc_next:	next tag bit to allocate
  * @tag_alloc_last:	next tag bit to be freed
@@ -150,6 +152,8 @@ enum pkt_vec {
 struct nfp_app_bpf {
 	struct nfp_app *app;
 
+	struct bpf_offload_dev *bpf_dev;
+
 	DECLARE_BITMAP(tag_allocator, U16_MAX + 1);
 	u16 tag_alloc_next;
 	u16 tag_alloc_last;
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index c4a2829e0e1f..9eab29f67a0e 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -592,11 +592,16 @@ int nsim_bpf_init(struct netdevsim *ns)
 			debugfs_create_dir("bpf_bound_progs", ns->sdev->ddir);
 		if (IS_ERR_OR_NULL(ns->sdev->ddir_bpf_bound_progs))
 			return -ENOMEM;
+
+		ns->sdev->bpf_dev = bpf_offload_dev_create();
+		err = PTR_ERR_OR_ZERO(ns->sdev->bpf_dev);
+		if (err)
+			return err;
 	}
 
-	err = bpf_offload_dev_netdev_register(ns->netdev);
+	err = bpf_offload_dev_netdev_register(ns->sdev->bpf_dev, ns->netdev);
 	if (err)
-		return err;
+		goto err_destroy_bdev;
 
 	debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir,
 			   &ns->bpf_offloaded_id);
@@ -624,6 +629,11 @@ int nsim_bpf_init(struct netdevsim *ns)
 			    &ns->bpf_map_accept);
 
 	return 0;
+
+err_destroy_bdev:
+	if (ns->sdev->refcnt == 1)
+		bpf_offload_dev_destroy(ns->sdev->bpf_dev);
+	return err;
 }
 
 void nsim_bpf_uninit(struct netdevsim *ns)
@@ -631,10 +641,11 @@ void nsim_bpf_uninit(struct netdevsim *ns)
 	WARN_ON(ns->xdp.prog);
 	WARN_ON(ns->xdp_hw.prog);
 	WARN_ON(ns->bpf_offloaded);
-	bpf_offload_dev_netdev_unregister(ns->netdev);
+	bpf_offload_dev_netdev_unregister(ns->sdev->bpf_dev, ns->netdev);
 
 	if (ns->sdev->refcnt == 1) {
 		WARN_ON(!list_empty(&ns->sdev->bpf_bound_progs));
 		WARN_ON(!list_empty(&ns->sdev->bpf_bound_maps));
+		bpf_offload_dev_destroy(ns->sdev->bpf_dev);
 	}
 }
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 98f26fa1e671..02be199eb005 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -27,6 +27,7 @@
 #define NSIM_EA(extack, msg)	NL_SET_ERR_MSG_MOD((extack), msg)
 
 struct bpf_prog;
+struct bpf_offload_dev;
 struct dentry;
 struct nsim_vf_config;
 
@@ -36,6 +37,8 @@ struct netdevsim_shared_dev {
 
 	struct dentry *ddir;
 
+	struct bpf_offload_dev *bpf_dev;
+
 	struct dentry *ddir_bpf_bound_progs;
 	u32 prog_id_gen;
 
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 21c001c3285c..cd947441782e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -85,6 +85,7 @@ struct bpf_map {
 	char name[BPF_OBJ_NAME_LEN];
 };
 
+struct bpf_offload_dev;
 struct bpf_offloaded_map;
 
 struct bpf_map_dev_ops {
@@ -648,9 +649,14 @@ int bpf_map_offload_delete_elem(struct bpf_map *map, void *key);
 int bpf_map_offload_get_next_key(struct bpf_map *map,
 				 void *key, void *next_key);
 
-int bpf_offload_dev_netdev_register(struct net_device *netdev);
-void bpf_offload_dev_netdev_unregister(struct net_device *netdev);
-bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map);
+struct bpf_offload_dev *bpf_offload_dev_create(void);
+void bpf_offload_dev_destroy(struct bpf_offload_dev *offdev);
+int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
+				    struct net_device *netdev);
+void bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
+				       struct net_device *netdev);
+bool bpf_offload_match(struct bpf_prog *prog, struct bpf_map *map);
+bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev);
 
 #if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
 int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr);
diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c
index b914f94c53d4..e090ec00390d 100644
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@ -32,11 +32,17 @@
  */
 static DECLARE_RWSEM(bpf_devs_lock);
 
+struct bpf_offload_dev {
+	struct list_head netdevs;
+};
+
 struct bpf_offload_netdev {
 	struct rhash_head l;
 	struct net_device *netdev;
+	struct bpf_offload_dev *offdev;
 	struct list_head progs;
 	struct list_head maps;
+	struct list_head offdev_netdevs;
 };
 
 static const struct rhashtable_params offdevs_params = {
@@ -505,46 +511,67 @@ int bpf_map_offload_info_fill(struct bpf_map_info *info, struct bpf_map *map)
 	return 0;
 }
 
-bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map)
+static bool __bpf_offload_dev_match(struct bpf_prog *prog,
+				    struct net_device *netdev)
 {
-	struct bpf_offloaded_map *offmap;
+	struct bpf_offload_netdev *ondev1, *ondev2;
 	struct bpf_prog_offload *offload;
-	bool ret;
 
 	if (!bpf_prog_is_dev_bound(prog->aux))
 		return false;
-	if (!bpf_map_is_dev_bound(map))
-		return bpf_map_offload_neutral(map);
 
-	down_read(&bpf_devs_lock);
 	offload = prog->aux->offload;
+	if (!offload)
+		return false;
+	if (offload->netdev == netdev)
+		return true;
+
+	ondev1 = bpf_offload_find_netdev(offload->netdev);
+	ondev2 = bpf_offload_find_netdev(netdev);
+
+	return ondev1 && ondev2 && ondev1->offdev == ondev2->offdev;
+}
+
+bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev)
+{
+	bool ret;
+
+	down_read(&bpf_devs_lock);
+	ret = __bpf_offload_dev_match(prog, netdev);
+	up_read(&bpf_devs_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bpf_offload_dev_match);
+
+bool bpf_offload_match(struct bpf_prog *prog, struct bpf_map *map)
+{
+	struct bpf_offloaded_map *offmap;
+	bool ret;
+
+	if (!bpf_map_is_dev_bound(map))
+		return bpf_map_offload_neutral(map);
 	offmap = map_to_offmap(map);
 
-	ret = offload && offload->netdev == offmap->netdev;
+	down_read(&bpf_devs_lock);
+	ret = __bpf_offload_dev_match(prog, offmap->netdev);
 	up_read(&bpf_devs_lock);
 
 	return ret;
 }
 
-int bpf_offload_dev_netdev_register(struct net_device *netdev)
+int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
+				    struct net_device *netdev)
 {
 	struct bpf_offload_netdev *ondev;
 	int err;
 
-	down_write(&bpf_devs_lock);
-	if (!offdevs_inited) {
-		err = rhashtable_init(&offdevs, &offdevs_params);
-		if (err)
-			return err;
-		offdevs_inited = true;
-	}
-	up_write(&bpf_devs_lock);
-
 	ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
 	if (!ondev)
 		return -ENOMEM;
 
 	ondev->netdev = netdev;
+	ondev->offdev = offdev;
 	INIT_LIST_HEAD(&ondev->progs);
 	INIT_LIST_HEAD(&ondev->maps);
 
@@ -555,6 +582,7 @@ int bpf_offload_dev_netdev_register(struct net_device *netdev)
 		goto err_unlock_free;
 	}
 
+	list_add(&ondev->offdev_netdevs, &offdev->netdevs);
 	up_write(&bpf_devs_lock);
 	return 0;
 
@@ -565,11 +593,12 @@ int bpf_offload_dev_netdev_register(struct net_device *netdev)
 }
 EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_register);
 
-void bpf_offload_dev_netdev_unregister(struct net_device *netdev)
+void bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
+				       struct net_device *netdev)
 {
+	struct bpf_offload_netdev *ondev, *altdev;
 	struct bpf_offloaded_map *offmap, *mtmp;
 	struct bpf_prog_offload *offload, *ptmp;
-	struct bpf_offload_netdev *ondev;
 
 	ASSERT_RTNL();
 
@@ -579,11 +608,26 @@ void bpf_offload_dev_netdev_unregister(struct net_device *netdev)
 		goto unlock;
 
 	WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
-
-	list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
-		__bpf_prog_offload_destroy(offload->prog);
-	list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
-		__bpf_map_offload_destroy(offmap);
+	list_del(&ondev->offdev_netdevs);
+
+	/* Try to move the objects to another netdev of the device */
+	altdev = list_first_entry_or_null(&offdev->netdevs,
+					  struct bpf_offload_netdev,
+					  offdev_netdevs);
+	if (altdev) {
+		list_for_each_entry(offload, &ondev->progs, offloads)
+			offload->netdev = altdev->netdev;
+		list_splice_init(&ondev->progs, &altdev->progs);
+
+		list_for_each_entry(offmap, &ondev->maps, offloads)
+			offmap->netdev = altdev->netdev;
+		list_splice_init(&ondev->maps, &altdev->maps);
+	} else {
+		list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
+			__bpf_prog_offload_destroy(offload->prog);
+		list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
+			__bpf_map_offload_destroy(offmap);
+	}
 
 	WARN_ON(!list_empty(&ondev->progs));
 	WARN_ON(!list_empty(&ondev->maps));
@@ -592,3 +636,34 @@ void bpf_offload_dev_netdev_unregister(struct net_device *netdev)
 	up_write(&bpf_devs_lock);
 }
 EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_unregister);
+
+struct bpf_offload_dev *bpf_offload_dev_create(void)
+{
+	struct bpf_offload_dev *offdev;
+	int err;
+
+	down_write(&bpf_devs_lock);
+	if (!offdevs_inited) {
+		err = rhashtable_init(&offdevs, &offdevs_params);
+		if (err)
+			return ERR_PTR(err);
+		offdevs_inited = true;
+	}
+	up_write(&bpf_devs_lock);
+
+	offdev = kzalloc(sizeof(*offdev), GFP_KERNEL);
+	if (!offdev)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&offdev->netdevs);
+
+	return offdev;
+}
+EXPORT_SYMBOL_GPL(bpf_offload_dev_create);
+
+void bpf_offload_dev_destroy(struct bpf_offload_dev *offdev)
+{
+	WARN_ON(!list_empty(&offdev->netdevs));
+	kfree(offdev);
+}
+EXPORT_SYMBOL_GPL(bpf_offload_dev_destroy);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 9e2bf834f13a..2c5b923eef75 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5054,7 +5054,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
 	}
 
 	if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) &&
-	    !bpf_offload_dev_match(prog, map)) {
+	    !bpf_offload_match(prog, map)) {
 		verbose(env, "offload device mismatch between prog and map\n");
 		return -EINVAL;
 	}
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 8/9] nfp: bpf: allow program sharing within ASIC
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Allow program sharing between netdevs of the same NFP ASIC.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/bpf/offload.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
index 78f44c4d95b4..49b03f7dbf46 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
@@ -566,14 +566,8 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
 {
 	int err;
 
-	if (prog) {
-		struct bpf_prog_offload *offload = prog->aux->offload;
-
-		if (!offload)
-			return -EINVAL;
-		if (offload->netdev != nn->dp.netdev)
-			return -EINVAL;
-	}
+	if (prog && !bpf_offload_dev_match(prog, nn->dp.netdev))
+		return -EINVAL;
 
 	if (prog && old_prog) {
 		u8 cap;
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 9/9] selftests/bpf: add test for sharing objects between netdevs
From: Jakub Kicinski @ 2018-07-17  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, daniel; +Cc: oss-drivers, netdev, Jakub Kicinski
In-Reply-To: <20180717023723.30155-1-jakub.kicinski@netronome.com>

Add tests for sharing programs and maps between different netdevs.
Use netdevsim's ability to pretend multiple netdevs belong to the
same "ASIC".

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 tools/testing/selftests/bpf/test_offload.py | 146 +++++++++++++++++++-
 1 file changed, 142 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py
index ee1abef384ea..d59642e70f56 100755
--- a/tools/testing/selftests/bpf/test_offload.py
+++ b/tools/testing/selftests/bpf/test_offload.py
@@ -158,8 +158,9 @@ netns = [] # net namespaces to be removed
     else:
         return ret, out
 
-def bpftool(args, JSON=True, ns="", fail=True):
-    return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns, fail=fail)
+def bpftool(args, JSON=True, ns="", fail=True, include_stderr=False):
+    return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns,
+                fail=fail, include_stderr=include_stderr)
 
 def bpftool_prog_list(expected=None, ns=""):
     _, progs = bpftool("prog show", JSON=True, ns=ns, fail=True)
@@ -201,6 +202,21 @@ netns = [] # net namespaces to be removed
         time.sleep(0.05)
     raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps))
 
+def bpftool_prog_load(sample, file_name, maps=[], prog_type="xdp", dev=None,
+                      fail=True, include_stderr=False):
+    args = "prog load %s %s" % (os.path.join(bpf_test_dir, sample), file_name)
+    if prog_type is not None:
+        args += " type " + prog_type
+    if dev is not None:
+        args += " dev " + dev
+    if len(maps):
+        args += " map " + " map ".join(maps)
+
+    res = bpftool(args, fail=fail, include_stderr=include_stderr)
+    if res[0] == 0:
+        files.append(file_name)
+    return res
+
 def ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False):
     if force:
         args = "-force " + args
@@ -307,7 +323,9 @@ netns = [] # net namespaces to be removed
     Class for netdevsim netdevice and its attributes.
     """
 
-    def __init__(self):
+    def __init__(self, link=None):
+        self.link = link
+
         self.dev = self._netdevsim_create()
         devs.append(self)
 
@@ -321,8 +339,9 @@ netns = [] # net namespaces to be removed
         return self.dev[key]
 
     def _netdevsim_create(self):
+        link = "" if self.link is None else "link " + self.link.dev['ifname']
         _, old  = ip("link show")
-        ip("link add sim%d type netdevsim")
+        ip("link add sim%d {link} type netdevsim".format(link=link))
         _, new  = ip("link show")
 
         for dev in new:
@@ -848,6 +867,25 @@ netns = []
     sim.set_mtu(1500)
 
     sim.wait_for_flush()
+    start_test("Test non-offload XDP attaching to HW...")
+    bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/nooffload")
+    nooffload = bpf_pinned("/sys/fs/bpf/nooffload")
+    ret, _, err = sim.set_xdp(nooffload, "offload",
+                              fail=False, include_stderr=True)
+    fail(ret == 0, "attached non-offloaded XDP program to HW")
+    check_extack_nsim(err, "xdpoffload of non-bound program.", args)
+    rm("/sys/fs/bpf/nooffload")
+
+    start_test("Test offload XDP attaching to drv...")
+    bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/offload",
+                      dev=sim['ifname'])
+    offload = bpf_pinned("/sys/fs/bpf/offload")
+    ret, _, err = sim.set_xdp(offload, "drv", fail=False, include_stderr=True)
+    fail(ret == 0, "attached offloaded XDP program to drv")
+    check_extack(err, "using device-bound program without HW_MODE flag is not supported.", args)
+    rm("/sys/fs/bpf/offload")
+    sim.wait_for_flush()
+
     start_test("Test XDP offload...")
     _, _, err = sim.set_xdp(obj, "offload", verbose=True, include_stderr=True)
     ipl = sim.ip_link_show(xdp=True)
@@ -1141,6 +1179,106 @@ netns = []
     fail(ret == 0,
          "netdevsim didn't refuse to create a map with offload disabled")
 
+    sim.remove()
+
+    start_test("Test multi-dev ASIC program reuse...")
+    simA = NetdevSim()
+    simB1 = NetdevSim()
+    simB2 = NetdevSim(link=simB1)
+    simB3 = NetdevSim(link=simB1)
+    sims = (simA, simB1, simB2, simB3)
+    simB = (simB1, simB2, simB3)
+
+    bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimA",
+                      dev=simA['ifname'])
+    progA = bpf_pinned("/sys/fs/bpf/nsimA")
+    bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB",
+                      dev=simB1['ifname'])
+    progB = bpf_pinned("/sys/fs/bpf/nsimB")
+
+    simA.set_xdp(progA, "offload", JSON=False)
+    for d in simB:
+        d.set_xdp(progB, "offload", JSON=False)
+
+    start_test("Test multi-dev ASIC cross-dev replace...")
+    ret, _ = simA.set_xdp(progB, "offload", force=True, JSON=False, fail=False)
+    fail(ret == 0, "cross-ASIC program allowed")
+    for d in simB:
+        ret, _ = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False)
+        fail(ret == 0, "cross-ASIC program allowed")
+
+    start_test("Test multi-dev ASIC cross-dev install...")
+    for d in sims:
+        d.unset_xdp("offload")
+
+    ret, _, err = simA.set_xdp(progB, "offload", force=True, JSON=False,
+                               fail=False, include_stderr=True)
+    fail(ret == 0, "cross-ASIC program allowed")
+    check_extack_nsim(err, "program bound to different dev.", args)
+    for d in simB:
+        ret, _, err = d.set_xdp(progA, "offload", force=True, JSON=False,
+                                fail=False, include_stderr=True)
+        fail(ret == 0, "cross-ASIC program allowed")
+        check_extack_nsim(err, "program bound to different dev.", args)
+
+    start_test("Test multi-dev ASIC cross-dev map reuse...")
+
+    mapA = bpftool("prog show %s" % (progA))[1]["map_ids"][0]
+    mapB = bpftool("prog show %s" % (progB))[1]["map_ids"][0]
+
+    ret, _ = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB_",
+                               dev=simB3['ifname'],
+                               maps=["idx 0 id %d" % (mapB)],
+                               fail=False)
+    fail(ret != 0, "couldn't reuse a map on the same ASIC")
+    rm("/sys/fs/bpf/nsimB_")
+
+    ret, _, err = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimA_",
+                                    dev=simA['ifname'],
+                                    maps=["idx 0 id %d" % (mapB)],
+                                    fail=False, include_stderr=True)
+    fail(ret == 0, "could reuse a map on a different ASIC")
+    fail(err.count("offload device mismatch between prog and map") == 0,
+         "error message missing for cross-ASIC map")
+
+    ret, _, err = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB_",
+                                    dev=simB1['ifname'],
+                                    maps=["idx 0 id %d" % (mapA)],
+                                    fail=False, include_stderr=True)
+    fail(ret == 0, "could reuse a map on a different ASIC")
+    fail(err.count("offload device mismatch between prog and map") == 0,
+         "error message missing for cross-ASIC map")
+
+    start_test("Test multi-dev ASIC cross-dev destruction...")
+    bpftool_prog_list_wait(expected=2)
+
+    simA.remove()
+    bpftool_prog_list_wait(expected=1)
+
+    ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"]
+    fail(ifnameB != simB1['ifname'], "program not bound to originial device")
+    simB1.remove()
+    bpftool_prog_list_wait(expected=1)
+
+    start_test("Test multi-dev ASIC cross-dev destruction - move...")
+    ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"]
+    fail(ifnameB not in (simB2['ifname'], simB3['ifname']),
+         "program not bound to remaining devices")
+
+    simB2.remove()
+    ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"]
+    fail(ifnameB != simB3['ifname'], "program not bound to remaining device")
+
+    simB3.remove()
+    bpftool_prog_list_wait(expected=0)
+
+    start_test("Test multi-dev ASIC cross-dev destruction - orphaned...")
+    ret, out = bpftool("prog show %s" % (progB), fail=False)
+    fail(ret == 0, "got information about orphaned program")
+    fail("error" not in out, "no error reported for get info on orphaned")
+    fail(out["error"] != "can't get prog info: No such device",
+         "wrong error for get info on orphaned")
+
     print("%s: OK" % (os.path.basename(__file__)))
 
 finally:
-- 
2.17.1

^ permalink raw reply related

* Re: [PATCH bpf-next 6/9] bpf: offload: allow program and map sharing per-ASIC
From: Alexei Starovoitov @ 2018-07-17  3:00 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: daniel, oss-drivers, netdev
In-Reply-To: <20180717023723.30155-7-jakub.kicinski@netronome.com>

On Mon, Jul 16, 2018 at 07:37:20PM -0700, Jakub Kicinski wrote:
> Create a higher-level entity to represent a device/ASIC to allow
> programs and maps to be shared between device ports.  The extra
> work is required to make sure we don't destroy BPF objects as
> soon as the netdev for which they were loaded gets destroyed,
> as other ports may still be using them.  When netdev goes away
> all of its BPF objects will be moved to other netdevs of the
> device, and only destroyed when last netdev is unregistered.
> 
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
..
> -bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map)
> +static bool __bpf_offload_dev_match(struct bpf_prog *prog,
> +				    struct net_device *netdev)
>  {
> -	struct bpf_offloaded_map *offmap;
> +	struct bpf_offload_netdev *ondev1, *ondev2;
>  	struct bpf_prog_offload *offload;
> -	bool ret;
>  
>  	if (!bpf_prog_is_dev_bound(prog->aux))
>  		return false;
> -	if (!bpf_map_is_dev_bound(map))
> -		return bpf_map_offload_neutral(map);
>  
> -	down_read(&bpf_devs_lock);
>  	offload = prog->aux->offload;
> +	if (!offload)
> +		return false;
> +	if (offload->netdev == netdev)
> +		return true;
> +
> +	ondev1 = bpf_offload_find_netdev(offload->netdev);
> +	ondev2 = bpf_offload_find_netdev(netdev);
> +
> +	return ondev1 && ondev2 && ondev1->offdev == ondev2->offdev;
> +}
> +
> +bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev)
> +{
> +	bool ret;
> +
> +	down_read(&bpf_devs_lock);
> +	ret = __bpf_offload_dev_match(prog, netdev);
> +	up_read(&bpf_devs_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(bpf_offload_dev_match);
> +
> +bool bpf_offload_match(struct bpf_prog *prog, struct bpf_map *map)
> +{
> +	struct bpf_offloaded_map *offmap;
> +	bool ret;
> +
> +	if (!bpf_map_is_dev_bound(map))
> +		return bpf_map_offload_neutral(map);
>  	offmap = map_to_offmap(map);
>  
> -	ret = offload && offload->netdev == offmap->netdev;
> +	down_read(&bpf_devs_lock);
> +	ret = __bpf_offload_dev_match(prog, offmap->netdev);
>  	up_read(&bpf_devs_lock);
>  
>  	return ret;
>  }
>  
..
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 9e2bf834f13a..2c5b923eef75 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -5054,7 +5054,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
>  	}
>  
>  	if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) &&
> -	    !bpf_offload_dev_match(prog, map)) {
> +	    !bpf_offload_match(prog, map)) {

I'm confused with new names and renaming.
May be split renaming into separate patch?
Should new bpf_offload_match() be called bpf_offload_prog_map_match() ?
or some other name?
May be adding comments to these functions will make it clear...

^ permalink raw reply

* Re: [PATCH bpf-next 6/9] bpf: offload: allow program and map sharing per-ASIC
From: Jakub Kicinski @ 2018-07-17  3:18 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: daniel, oss-drivers, netdev
In-Reply-To: <20180717030046.4ylnjs3lkdar4uld@ast-mbp.dhcp.thefacebook.com>

On Mon, 16 Jul 2018 20:00:47 -0700, Alexei Starovoitov wrote:
> On Mon, Jul 16, 2018 at 07:37:20PM -0700, Jakub Kicinski wrote:
> > Create a higher-level entity to represent a device/ASIC to allow
> > programs and maps to be shared between device ports.  The extra
> > work is required to make sure we don't destroy BPF objects as
> > soon as the netdev for which they were loaded gets destroyed,
> > as other ports may still be using them.  When netdev goes away
> > all of its BPF objects will be moved to other netdevs of the
> > device, and only destroyed when last netdev is unregistered.
> > 
> > Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> > Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>  
> ..
> > -bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map)
> > +static bool __bpf_offload_dev_match(struct bpf_prog *prog,
> > +				    struct net_device *netdev)
> >  {
> > -	struct bpf_offloaded_map *offmap;
> > +	struct bpf_offload_netdev *ondev1, *ondev2;
> >  	struct bpf_prog_offload *offload;
> > -	bool ret;
> >  
> >  	if (!bpf_prog_is_dev_bound(prog->aux))
> >  		return false;
> > -	if (!bpf_map_is_dev_bound(map))
> > -		return bpf_map_offload_neutral(map);
> >  
> > -	down_read(&bpf_devs_lock);
> >  	offload = prog->aux->offload;
> > +	if (!offload)
> > +		return false;
> > +	if (offload->netdev == netdev)
> > +		return true;
> > +
> > +	ondev1 = bpf_offload_find_netdev(offload->netdev);
> > +	ondev2 = bpf_offload_find_netdev(netdev);
> > +
> > +	return ondev1 && ondev2 && ondev1->offdev == ondev2->offdev;
> > +}
> > +
> > +bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev)
> > +{
> > +	bool ret;
> > +
> > +	down_read(&bpf_devs_lock);
> > +	ret = __bpf_offload_dev_match(prog, netdev);
> > +	up_read(&bpf_devs_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(bpf_offload_dev_match);
> > +
> > +bool bpf_offload_match(struct bpf_prog *prog, struct bpf_map *map)
> > +{
> > +	struct bpf_offloaded_map *offmap;
> > +	bool ret;
> > +
> > +	if (!bpf_map_is_dev_bound(map))
> > +		return bpf_map_offload_neutral(map);
> >  	offmap = map_to_offmap(map);
> >  
> > -	ret = offload && offload->netdev == offmap->netdev;
> > +	down_read(&bpf_devs_lock);
> > +	ret = __bpf_offload_dev_match(prog, offmap->netdev);
> >  	up_read(&bpf_devs_lock);
> >  
> >  	return ret;
> >  }
> >    
> ..
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 9e2bf834f13a..2c5b923eef75 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -5054,7 +5054,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
> >  	}
> >  
> >  	if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) &&
> > -	    !bpf_offload_dev_match(prog, map)) {
> > +	    !bpf_offload_match(prog, map)) {  
> 
> I'm confused with new names and renaming.
> May be split renaming into separate patch?
> Should new bpf_offload_match() be called bpf_offload_prog_map_match() ?
> or some other name?
> May be adding comments to these functions will make it clear...

It is messy.  The new functions to register/unregister ASIC are called
bpf_offload_dev_*, hence it seemed like a good idea to call the
function exported to the drivers bpf_offload_dev_match() (see patches 7
and 8) to keep the driver API consistent.  But then the old function
which is only used by the verivier has to be renamed.

I will use bpf_offload_prog_map_match() and split to a separate patch.

^ permalink raw reply

* [PATCH v2] net: dsa: Remove VLA usage
From: Kees Cook @ 2018-07-17  4:10 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev, linux-kernel, Salvatore Mesoraca, Florian Fainelli,
	Andrew Lunn, David Laight

From: Salvatore Mesoraca <s.mesoraca16@gmail.com>

We avoid 2 VLAs by using a pre-allocated field in dsa_switch. We also
try to avoid dynamic allocation whenever possible (when using fewer than
bits-per-long ports, which is the common case).

Link: http://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Link: http://lkml.kernel.org/r/20180505185145.GB32630@lunn.ch
Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com>
[kees: tweak commit subject and message slightly]
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/dsa.h |  3 +++
 net/dsa/dsa2.c    | 14 ++++++++++++++
 net/dsa/switch.c  | 22 ++++++++++------------
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index fdbd6082945d..461e8a7661b7 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -259,6 +259,9 @@ struct dsa_switch {
 	/* Number of switch port queues */
 	unsigned int		num_tx_queues;
 
+	unsigned long		*bitmap;
+	unsigned long		_bitmap;
+
 	/* Dynamically allocated ports, keep last */
 	size_t num_ports;
 	struct dsa_port ports[];
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index dc5d9af3dc80..a1917025e155 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -775,6 +775,20 @@ struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n)
 	if (!ds)
 		return NULL;
 
+	/* We avoid allocating memory outside dsa_switch
+	 * if it is not needed.
+	 */
+	if (n <= sizeof(ds->_bitmap) * 8) {
+		ds->bitmap = &ds->_bitmap;
+	} else {
+		ds->bitmap = devm_kcalloc(dev,
+					  BITS_TO_LONGS(n),
+					  sizeof(unsigned long),
+					  GFP_KERNEL);
+		if (unlikely(!ds->bitmap))
+			return NULL;
+	}
+
 	ds->dev = dev;
 	ds->num_ports = n;
 
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index b93511726069..142b294d3446 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -136,21 +136,20 @@ static int dsa_switch_mdb_add(struct dsa_switch *ds,
 {
 	const struct switchdev_obj_port_mdb *mdb = info->mdb;
 	struct switchdev_trans *trans = info->trans;
-	DECLARE_BITMAP(group, ds->num_ports);
 	int port;
 
 	/* Build a mask of Multicast group members */
-	bitmap_zero(group, ds->num_ports);
+	bitmap_zero(ds->bitmap, ds->num_ports);
 	if (ds->index == info->sw_index)
-		set_bit(info->port, group);
+		set_bit(info->port, ds->bitmap);
 	for (port = 0; port < ds->num_ports; port++)
 		if (dsa_is_dsa_port(ds, port))
-			set_bit(port, group);
+			set_bit(port, ds->bitmap);
 
 	if (switchdev_trans_ph_prepare(trans))
-		return dsa_switch_mdb_prepare_bitmap(ds, mdb, group);
+		return dsa_switch_mdb_prepare_bitmap(ds, mdb, ds->bitmap);
 
-	dsa_switch_mdb_add_bitmap(ds, mdb, group);
+	dsa_switch_mdb_add_bitmap(ds, mdb, ds->bitmap);
 
 	return 0;
 }
@@ -204,21 +203,20 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
 {
 	const struct switchdev_obj_port_vlan *vlan = info->vlan;
 	struct switchdev_trans *trans = info->trans;
-	DECLARE_BITMAP(members, ds->num_ports);
 	int port;
 
 	/* Build a mask of VLAN members */
-	bitmap_zero(members, ds->num_ports);
+	bitmap_zero(ds->bitmap, ds->num_ports);
 	if (ds->index == info->sw_index)
-		set_bit(info->port, members);
+		set_bit(info->port, ds->bitmap);
 	for (port = 0; port < ds->num_ports; port++)
 		if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
-			set_bit(port, members);
+			set_bit(port, ds->bitmap);
 
 	if (switchdev_trans_ph_prepare(trans))
-		return dsa_switch_vlan_prepare_bitmap(ds, vlan, members);
+		return dsa_switch_vlan_prepare_bitmap(ds, vlan, ds->bitmap);
 
-	dsa_switch_vlan_add_bitmap(ds, vlan, members);
+	dsa_switch_vlan_add_bitmap(ds, vlan, ds->bitmap);
 
 	return 0;
 }
-- 
2.17.1


-- 
Kees Cook
Pixel Security

^ permalink raw reply related

* [PATCH net-next 0/3] Series to improve setsockopt() TCP_USER_TIMEOUT accuracy
From: Jon Maxwell @ 2018-07-17  4:15 UTC (permalink / raw)
  To: davem
  Cc: edumazet, ncardwell, David.Laight, kuznet, yoshfuji, netdev,
	linux-kernel, jmaxwell

This is a patch series based on:

https://patchwork.kernel.org/patch/10516195/

Every time the TCP retransmission timer fires. It checks to see if there is a 
timeout before scheduling the next retransmit timer. The retransmit interval 
between each retransmission increases exponentially. The issue is that in order 
for the timeout to occur the retransmit timer needs to fire again. If the user 
timeout check happens after the 9th retransmit for example. It needs to wait for 
the 10th retransmit timer to fire in order to evaluate whether a timeout has 
occurred or not. If the interval is large enough then the timeout will be 
inaccurate.

For example with a TCP_USER_TIMEOUT of 10 seconds without patch:

1st retransmit:

22:25:18.973488 IP host1.49310 > host2.search-agent: Flags [.]

Last retransmit:

22:25:26.205499 IP host1.49310 > host2.search-agent: Flags [.]

Timeout:

send: Connection timed out
Sun Jul  1 22:25:34 EDT 2018

We can see that last retransmit took ~7 seconds. Which pushed the total 
timeout to ~15 seconds instead of the expected 10 seconds. This gets more 
inaccurate the larger the TCP_USER_TIMEOUT value. As the interval increases.

Add tcp_clamp_rto_to_user_timeout() to determine if the user rto has expired.
Or whether the rto interval needs to be recalculated. Use the original interval
if user rto is not set. 

Test results with the patch is the expected 10 second timeout:

1st retransmit:

01:37:59.022555 IP host1.49310 > host2.search-agent: Flags [.]

Last retransmit:

01:38:06.486558 IP host1.49310 > host2.search-agent: Flags [.]

Timeout:

send: Connection timed out
Mon Jul  2 01:38:09 EDT 2018

Jon Maxwell (3):
  [PATCH net-next 1/3] tcp: convert icsk_user_timeout from jiffies to msecs
  [PATCH net-next v1 2/3] tcp: convert icsk_user_timeout from jiffies to msecs
  [PATCH net-next v1 3/3] tcp: convert icsk_user_timeout from jiffies to msecs

 net/ipv4/tcp.c       |  4 ++--
 net/ipv4/tcp_timer.c | 51 ++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 40 insertions(+), 15 deletions(-)

-- 
2.13.6

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox