Netdev List
 help / color / mirror / Atom feed
* [PATCH v2 24/28] thunderbolt: Add support for DMA tunnels
From: Mika Westerberg @ 2019-02-06 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Michael Jamet, Yehezkel Bernat, Andreas Noever, Lukas Wunner,
	David S . Miller, Mika Westerberg, Andy Shevchenko, netdev
In-Reply-To: <20190206131738.43696-1-mika.westerberg@linux.intel.com>

In addition to PCIe and Display Port tunnels it is also possible to
create tunnels that forward DMA traffic from the host interface adapter
(NHI) to a NULL port that is connected to another domain through a
Thunderbolt cable. These tunnels can be used to carry software messages
such as networking packets.

To support this we introduce another tunnel type (TB_TUNNEL_DMA) that
supports paths from NHI to NULL port and back.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/path.c    | 20 ++++++--
 drivers/thunderbolt/switch.c  | 22 ++++++++
 drivers/thunderbolt/tb.h      |  2 +
 drivers/thunderbolt/tb_regs.h |  3 ++
 drivers/thunderbolt/tunnel.c  | 94 ++++++++++++++++++++++++++++++++++-
 drivers/thunderbolt/tunnel.h  | 10 ++++
 6 files changed, 147 insertions(+), 4 deletions(-)

diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c
index ada60d4aa99b..afdb667fcc0d 100644
--- a/drivers/thunderbolt/path.c
+++ b/drivers/thunderbolt/path.c
@@ -284,7 +284,8 @@ static void __tb_path_deallocate_nfc(struct tb_path *path, int first_hop)
 	}
 }
 
-static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index)
+static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index,
+				    bool clear_fc)
 {
 	struct tb_regs_hop hop;
 	ktime_t timeout;
@@ -311,8 +312,20 @@ static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index)
 		if (ret)
 			return ret;
 
-		if (!hop.pending)
+		if (!hop.pending) {
+			if (clear_fc) {
+				/* Clear flow control */
+				hop.ingress_fc = 0;
+				hop.egress_fc = 0;
+				hop.ingress_shared_buffer = 0;
+				hop.egress_shared_buffer = 0;
+
+				return tb_port_write(port, &hop, TB_CFG_HOPS,
+						     2 * hop_index, 2);
+			}
+
 			return 0;
+		}
 
 		usleep_range(10, 20);
 	} while (ktime_before(ktime_get(), timeout));
@@ -326,7 +339,8 @@ static void __tb_path_deactivate_hops(struct tb_path *path, int first_hop)
 
 	for (i = first_hop; i < path->path_length; i++) {
 		res = __tb_path_deactivate_hop(path->hops[i].in_port,
-					       path->hops[i].in_hop_index);
+					       path->hops[i].in_hop_index,
+					       path->clear_fc);
 		if (res)
 			tb_port_warn(path->hops[i].in_port,
 				     "hop deactivation failed for hop %d, index %d\n",
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index a1876dcd1d10..13eed95fc667 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -562,6 +562,28 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits)
 			     TB_CFG_PORT, 4, 1);
 }
 
+/**
+ * tb_port_set_initial_credits() - Set initial port link credits allocated
+ * @port: Port to set the initial credits
+ * @credits: Number of credits to to allocate
+ *
+ * Set initial credits value to be used for ingress shared buffering.
+ */
+int tb_port_set_initial_credits(struct tb_port *port, u32 credits)
+{
+	u32 data;
+	int ret;
+
+	ret = tb_port_read(port, &data, TB_CFG_PORT, 5, 1);
+	if (ret)
+		return ret;
+
+	data &= ~TB_PORT_LCA_MASK;
+	data |= (credits << TB_PORT_LCA_SHIFT) & TB_PORT_LCA_MASK;
+
+	return tb_port_write(port, &data, TB_CFG_PORT, 5, 1);
+}
+
 /**
  * tb_port_clear_counter() - clear a counter in TB_CFG_COUNTER
  *
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 7e155eed1fee..3a42a47df69f 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -198,6 +198,7 @@ struct tb_path {
 	int weight:4;
 	bool drop_packages;
 	bool activated;
+	bool clear_fc;
 	struct tb_path_hop *hops;
 	int path_length; /* number of hops */
 };
@@ -465,6 +466,7 @@ static inline struct tb_switch *tb_to_switch(struct device *dev)
 
 int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
 int tb_port_add_nfc_credits(struct tb_port *port, int credits);
+int tb_port_set_initial_credits(struct tb_port *port, u32 credits);
 int tb_port_clear_counter(struct tb_port *port, int counter);
 int tb_port_alloc_in_hopid(struct tb_port *port, int hopid, int max_hopid);
 void tb_port_release_in_hopid(struct tb_port *port, int hopid);
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index 420d2a623f31..4591c8b1d546 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -215,6 +215,9 @@ struct tb_regs_port_header {
 #define TB_PORT_NFC_CREDITS_MASK	GENMASK(19, 0)
 #define TB_PORT_MAX_CREDITS_SHIFT	20
 #define TB_PORT_MAX_CREDITS_MASK	GENMASK(26, 20)
+/* DWORD 5 */
+#define TB_PORT_LCA_SHIFT		22
+#define TB_PORT_LCA_MASK		GENMASK(28, 22)
 
 /* Display Port adapter registers */
 
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index 7aab7e07739b..f10a0a15b873 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -26,7 +26,10 @@
 #define TB_DP_AUX_PATH_OUT		1
 #define TB_DP_AUX_PATH_IN		2
 
-static const char * const tb_tunnel_names[] = { "PCI", "DP" };
+#define TB_DMA_PATH_OUT			0
+#define TB_DMA_PATH_IN			1
+
+static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA" };
 
 #define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...)                   \
 	do {                                                            \
@@ -461,6 +464,95 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
 	return NULL;
 }
 
+static u32 tb_dma_credits(struct tb_port *nhi)
+{
+	u32 max_credits;
+
+	max_credits = nhi->config.nfc_credits & TB_PORT_MAX_CREDITS_MASK;
+	max_credits >>= TB_PORT_MAX_CREDITS_SHIFT;
+
+	return min(max_credits, 13U);
+}
+
+static int tb_dma_activate(struct tb_tunnel *tunnel, bool active)
+{
+	struct tb_port *nhi = tunnel->src_port;
+	u32 credits;
+
+	credits = active ? tb_dma_credits(nhi) : 0;
+	return tb_port_set_initial_credits(nhi, credits);
+}
+
+static void tb_dma_init_path(struct tb_path *path, unsigned int isb,
+			     unsigned int efc, u32 credits)
+{
+	int i;
+
+	path->egress_fc_enable = efc;
+	path->ingress_fc_enable = TB_PATH_ALL;
+	path->egress_shared_buffer = TB_PATH_NONE;
+	path->ingress_shared_buffer = isb;
+	path->priority = 5;
+	path->weight = 1;
+	path->clear_fc = true;
+
+	for (i = 0; i < path->path_length; i++)
+		path->hops[i].initial_credits = credits;
+}
+
+/**
+ * tb_tunnel_alloc_dma() - allocate a DMA tunnel
+ * @tb: Pointer to the domain structure
+ * @nhi: Host controller port
+ * @dst: Destination null port which the other domain is connected to
+ * @transmit_ring: NHI ring number used to send packets towards the
+ *		   other domain
+ * @transmit_path: HopID used for transmitting packets
+ * @receive_ring: NHI ring number used to receive packets from the
+ *		  other domain
+ * @reveive_path: HopID used for receiving packets
+ *
+ * Return: Returns a tb_tunnel on success or NULL on failure.
+ */
+struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
+				      struct tb_port *dst, int transmit_ring,
+				      int transmit_path, int receive_ring,
+				      int receive_path)
+{
+	struct tb_tunnel *tunnel;
+	struct tb_path *path;
+	u32 credits;
+
+	tunnel = tb_tunnel_alloc(tb, 2, TB_TUNNEL_DMA);
+	if (!tunnel)
+		return NULL;
+
+	tunnel->activate = tb_dma_activate;
+	tunnel->src_port = nhi;
+	tunnel->dst_port = dst;
+
+	credits = tb_dma_credits(nhi);
+
+	path = tb_path_alloc(tb, dst, nhi, receive_path, receive_ring, 0);
+	if (!path) {
+		tb_tunnel_free(tunnel);
+		return NULL;
+	}
+	tb_dma_init_path(path, TB_PATH_NONE, TB_PATH_SOURCE | TB_PATH_INTERNAL,
+			 credits);
+	tunnel->paths[TB_DMA_PATH_IN] = path;
+
+	path = tb_path_alloc(tb, nhi, dst, transmit_ring, transmit_path, 0);
+	if (!path) {
+		tb_tunnel_free(tunnel);
+		return NULL;
+	}
+	tb_dma_init_path(path, TB_PATH_SOURCE, TB_PATH_ALL, credits);
+	tunnel->paths[TB_DMA_PATH_OUT] = path;
+
+	return tunnel;
+}
+
 /**
  * tb_tunnel_free() - free a tunnel
  * @tunnel: Tunnel to be freed
diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h
index 07583f8247c1..fa51217e5925 100644
--- a/drivers/thunderbolt/tunnel.h
+++ b/drivers/thunderbolt/tunnel.h
@@ -14,6 +14,7 @@
 enum tb_tunnel_type {
 	TB_TUNNEL_PCI,
 	TB_TUNNEL_DP,
+	TB_TUNNEL_DMA,
 };
 
 /**
@@ -44,6 +45,10 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
 struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in);
 struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
 				     struct tb_port *out);
+struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
+				      struct tb_port *dst, int transmit_ring,
+				      int transmit_path, int receive_ring,
+				      int receive_path);
 
 void tb_tunnel_free(struct tb_tunnel *tunnel);
 int tb_tunnel_activate(struct tb_tunnel *tunnel);
@@ -61,5 +66,10 @@ static inline bool tb_tunnel_is_dp(const struct tb_tunnel *tunnel)
 	return tunnel->type == TB_TUNNEL_DP;
 }
 
+static inline bool tb_tunnel_is_dma(const struct tb_tunnel *tunnel)
+{
+	return tunnel->type == TB_TUNNEL_DMA;
+}
+
 #endif
 
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 28/28] thunderbolt: Start firmware on Titan Ridge Apple systems
From: Mika Westerberg @ 2019-02-06 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Michael Jamet, Yehezkel Bernat, Andreas Noever, Lukas Wunner,
	David S . Miller, Mika Westerberg, Andy Shevchenko, netdev
In-Reply-To: <20190206131738.43696-1-mika.westerberg@linux.intel.com>

Titan Ridge flow to start the firmware is the same as Alpine Ridge so we
can do the same on Titan Ridge based Apple systems.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/icm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
index c44906fac2a4..95cd391bfa8d 100644
--- a/drivers/thunderbolt/icm.c
+++ b/drivers/thunderbolt/icm.c
@@ -1190,6 +1190,8 @@ static struct pci_dev *get_upstream_port(struct pci_dev *pdev)
 	case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_BRIDGE:
 	case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE:
 	case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE:
+	case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_BRIDGE:
+	case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE:
 		return parent;
 	}
 
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 27/28] thunderbolt: Make rest of the logging to happen at debug level
From: Mika Westerberg @ 2019-02-06 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Michael Jamet, Yehezkel Bernat, Andreas Noever, Lukas Wunner,
	David S . Miller, Mika Westerberg, Andy Shevchenko, netdev
In-Reply-To: <20190206131738.43696-1-mika.westerberg@linux.intel.com>

Now that the driver can handle every possible tunnel types there is no
point to log everything as info level so turn these to happen at debug
level instead.

While at it remove duplicated tunnel activation log message
(tb_tunnel_activate() calls tb_tunnel_restart() which print the same
message).

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/ctl.c    |  2 +-
 drivers/thunderbolt/icm.c    |  2 +-
 drivers/thunderbolt/path.c   | 30 +++++++++++++++---------------
 drivers/thunderbolt/switch.c | 19 +++++++++----------
 drivers/thunderbolt/tb.c     | 11 +++++------
 drivers/thunderbolt/tunnel.c | 10 ++++------
 6 files changed, 35 insertions(+), 39 deletions(-)

diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
index 73b386de4d15..2427d73be731 100644
--- a/drivers/thunderbolt/ctl.c
+++ b/drivers/thunderbolt/ctl.c
@@ -720,7 +720,7 @@ int tb_cfg_error(struct tb_ctl *ctl, u64 route, u32 port,
 		.port = port,
 		.error = error,
 	};
-	tb_ctl_info(ctl, "resetting error on %llx:%x.\n", route, port);
+	tb_ctl_dbg(ctl, "resetting error on %llx:%x.\n", route, port);
 	return tb_ctl_tx(ctl, &pkg, sizeof(pkg), TB_CFG_PKG_ERROR);
 }
 
diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
index e28a4255d56a..c44906fac2a4 100644
--- a/drivers/thunderbolt/icm.c
+++ b/drivers/thunderbolt/icm.c
@@ -1559,7 +1559,7 @@ static int icm_firmware_start(struct tb *tb, struct tb_nhi *nhi)
 	if (val & REG_FW_STS_ICM_EN)
 		return 0;
 
-	dev_info(&nhi->pdev->dev, "starting ICM firmware\n");
+	dev_dbg(&nhi->pdev->dev, "starting ICM firmware\n");
 
 	ret = icm_firmware_reset(tb, nhi);
 	if (ret)
diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c
index afdb667fcc0d..1aefdef403ef 100644
--- a/drivers/thunderbolt/path.c
+++ b/drivers/thunderbolt/path.c
@@ -354,12 +354,12 @@ void tb_path_deactivate(struct tb_path *path)
 		tb_WARN(path->tb, "trying to deactivate an inactive path\n");
 		return;
 	}
-	tb_info(path->tb,
-		"deactivating path from %llx:%x to %llx:%x\n",
-		tb_route(path->hops[0].in_port->sw),
-		path->hops[0].in_port->port,
-		tb_route(path->hops[path->path_length - 1].out_port->sw),
-		path->hops[path->path_length - 1].out_port->port);
+	tb_dbg(path->tb,
+	       "deactivating path from %llx:%x to %llx:%x\n",
+	       tb_route(path->hops[0].in_port->sw),
+	       path->hops[0].in_port->port,
+	       tb_route(path->hops[path->path_length - 1].out_port->sw),
+	       path->hops[path->path_length - 1].out_port->port);
 	__tb_path_deactivate_hops(path, 0);
 	__tb_path_deallocate_nfc(path, 0);
 	path->activated = false;
@@ -382,12 +382,12 @@ int tb_path_activate(struct tb_path *path)
 		return -EINVAL;
 	}
 
-	tb_info(path->tb,
-		"activating path from %llx:%x to %llx:%x\n",
-		tb_route(path->hops[0].in_port->sw),
-		path->hops[0].in_port->port,
-		tb_route(path->hops[path->path_length - 1].out_port->sw),
-		path->hops[path->path_length - 1].out_port->port);
+	tb_dbg(path->tb,
+	       "activating path from %llx:%x to %llx:%x\n",
+	       tb_route(path->hops[0].in_port->sw),
+	       path->hops[0].in_port->port,
+	       tb_route(path->hops[path->path_length - 1].out_port->sw),
+	       path->hops[path->path_length - 1].out_port->port);
 
 	/* Clear counters. */
 	for (i = path->path_length - 1; i >= 0; i--) {
@@ -438,8 +438,8 @@ int tb_path_activate(struct tb_path *path)
 					    & out_mask;
 		hop.unknown3 = 0;
 
-		tb_port_info(path->hops[i].in_port, "Writing hop %d, index %d",
-			     i, path->hops[i].in_hop_index);
+		tb_port_dbg(path->hops[i].in_port, "Writing hop %d, index %d",
+			    i, path->hops[i].in_hop_index);
 		tb_dump_hop(path->hops[i].in_port, &hop);
 		res = tb_port_write(path->hops[i].in_port, &hop, TB_CFG_HOPS,
 				    2 * path->hops[i].in_hop_index, 2);
@@ -450,7 +450,7 @@ int tb_path_activate(struct tb_path *path)
 		}
 	}
 	path->activated = true;
-	tb_info(path->tb, "path activation complete\n");
+	tb_dbg(path->tb, "path activation complete\n");
 	return 0;
 err:
 	tb_WARN(path->tb, "path activation failed\n");
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 79391c3d834e..2b84b770b8d2 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -500,23 +500,22 @@ int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged)
 		if (state < 0)
 			return state;
 		if (state == TB_PORT_DISABLED) {
-			tb_port_info(port, "is disabled (state: 0)\n");
+			tb_port_dbg(port, "is disabled (state: 0)\n");
 			return 0;
 		}
 		if (state == TB_PORT_UNPLUGGED) {
 			if (wait_if_unplugged) {
 				/* used during resume */
-				tb_port_info(port,
-					     "is unplugged (state: 7), retrying...\n");
+				tb_port_dbg(port,
+					    "is unplugged (state: 7), retrying...\n");
 				msleep(100);
 				continue;
 			}
-			tb_port_info(port, "is unplugged (state: 7)\n");
+			tb_port_dbg(port, "is unplugged (state: 7)\n");
 			return 0;
 		}
 		if (state == TB_PORT_UP) {
-			tb_port_info(port,
-				     "is connected, link is up (state: 2)\n");
+			tb_port_dbg(port, "is connected, link is up (state: 2)\n");
 			return 1;
 		}
 
@@ -524,9 +523,9 @@ int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged)
 		 * After plug-in the state is TB_PORT_CONNECTING. Give it some
 		 * time.
 		 */
-		tb_port_info(port,
-			     "is connected, link is not up (state: %d), retrying...\n",
-			     state);
+		tb_port_dbg(port,
+			    "is connected, link is not up (state: %d), retrying...\n",
+			    state);
 		msleep(100);
 	}
 	tb_port_warn(port,
@@ -592,7 +591,7 @@ int tb_port_set_initial_credits(struct tb_port *port, u32 credits)
 int tb_port_clear_counter(struct tb_port *port, int counter)
 {
 	u32 zero[3] = { 0, 0, 0 };
-	tb_port_info(port, "clearing counter %d\n", counter);
+	tb_port_dbg(port, "clearing counter %d\n", counter);
 	return tb_port_write(port, zero, TB_CFG_COUNTERS, 3 * counter, 3);
 }
 
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 94dd1fd12967..3fda11d45a03 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -514,18 +514,17 @@ static void tb_handle_hotplug(struct work_struct *work)
 		} else if (tb_port_is_dpout(port)) {
 			tb_teardown_dp(tb, port);
 		} else {
-			tb_port_info(port,
-				     "got unplug event for disconnected port, ignoring\n");
+			tb_port_dbg(port,
+				   "got unplug event for disconnected port, ignoring\n");
 		}
 	} else if (port->remote) {
-		tb_port_info(port,
-			     "got plug event for connected port, ignoring\n");
+		tb_port_dbg(port, "got plug event for connected port, ignoring\n");
 	} else {
 		if (tb_port_is_null(port)) {
-			tb_port_info(port, "hotplug: scanning\n");
+			tb_port_dbg(port, "hotplug: scanning\n");
 			tb_scan_port(port);
 			if (!port->remote)
-				tb_port_info(port, "hotplug: no switch found\n");
+				tb_port_dbg(port, "hotplug: no switch found\n");
 		} else if (tb_port_is_dpout(port)) {
 			tb_tunnel_dp(tb, port);
 		}
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index f10a0a15b873..daacd700df6d 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -47,8 +47,8 @@ static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA" };
 	__TB_TUNNEL_PRINT(tb_WARN, tunnel, fmt, ##arg)
 #define tb_tunnel_warn(tunnel, fmt, arg...) \
 	__TB_TUNNEL_PRINT(tb_warn, tunnel, fmt, ##arg)
-#define tb_tunnel_info(tunnel, fmt, arg...) \
-	__TB_TUNNEL_PRINT(tb_info, tunnel, fmt, ##arg)
+#define tb_tunnel_dbg(tunnel, fmt, arg...) \
+	__TB_TUNNEL_PRINT(tb_dbg, tunnel, fmt, ##arg)
 
 static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths,
 					 enum tb_tunnel_type type)
@@ -610,7 +610,7 @@ int tb_tunnel_restart(struct tb_tunnel *tunnel)
 {
 	int res, i;
 
-	tb_tunnel_info(tunnel, "activating\n");
+	tb_tunnel_dbg(tunnel, "activating\n");
 
 	/* Make sure all paths are properly disabled before enable them again */
 	for (i = 0; i < tunnel->npaths; i++) {
@@ -650,8 +650,6 @@ int tb_tunnel_activate(struct tb_tunnel *tunnel)
 {
 	int i;
 
-	tb_tunnel_info(tunnel, "activating\n");
-
 	for (i = 0; i < tunnel->npaths; i++) {
 		if (tunnel->paths[i]->activated) {
 			tb_tunnel_WARN(tunnel,
@@ -671,7 +669,7 @@ void tb_tunnel_deactivate(struct tb_tunnel *tunnel)
 {
 	int i;
 
-	tb_tunnel_info(tunnel, "deactivating\n");
+	tb_tunnel_dbg(tunnel, "deactivating\n");
 
 	if (tunnel->activate)
 		tunnel->activate(tunnel, false);
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 17/28] thunderbolt: Add support for full PCIe daisy chains
From: Mika Westerberg @ 2019-02-06 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Michael Jamet, Yehezkel Bernat, Andreas Noever, Lukas Wunner,
	David S . Miller, Mika Westerberg, Andy Shevchenko, netdev
In-Reply-To: <20190206131738.43696-1-mika.westerberg@linux.intel.com>

Currently the software connection manager (tb.c) has only supported
creating a single PCIe tunnel, no PCIe device daisy chaining has been
supported so far. This updates the software connection manager so that
it now can create PCIe tunnels for full chain of six devices.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/tb.c | 174 +++++++++++++++++++++++----------------
 1 file changed, 104 insertions(+), 70 deletions(-)

diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 371633e17916..f2b23b290b63 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -1,8 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Thunderbolt Cactus Ridge driver - bus logic (NHI independent)
+ * Thunderbolt driver - bus logic (NHI independent)
  *
  * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
+ * Copyright (C) 2019, Intel Corporation
  */
 
 #include <linux/slab.h>
@@ -50,8 +51,15 @@ static void tb_discover_tunnels(struct tb_switch *sw)
 		}
 
 		/* Find and add existing tunnels */
-		if (tunnel)
+		if (tunnel) {
+			struct tb_port *p;
+
+			/* Firmware added switches are always authorized */
+			tb_for_each_port(p, tunnel->src_port, tunnel->dst_port)
+				p->sw->boot = true;
+
 			list_add_tail(&tunnel->list, &tcm->tunnel_list);
+		}
 	}
 
 	for (i = 1; i <= sw->config.max_port_number; i++) {
@@ -63,6 +71,16 @@ static void tb_discover_tunnels(struct tb_switch *sw)
 	}
 }
 
+static void tb_switch_authorize(struct work_struct *work)
+{
+	struct tb_switch *sw = container_of(work, typeof(*sw), work);
+
+	mutex_lock(&sw->tb->lock);
+	if (!sw->is_unplugged)
+		tb_domain_approve_switch(sw->tb, sw);
+	mutex_unlock(&sw->tb->lock);
+}
+
 static void tb_scan_port(struct tb_port *port);
 
 /**
@@ -80,6 +98,7 @@ static void tb_scan_switch(struct tb_switch *sw)
  */
 static void tb_scan_port(struct tb_port *port)
 {
+	struct tb_cm *tcm = tb_priv(port->sw->tb);
 	struct tb_switch *sw;
 	if (tb_is_upstream_port(port))
 		return;
@@ -106,6 +125,14 @@ static void tb_scan_port(struct tb_port *port)
 		return;
 	}
 
+	/*
+	 * Do not send uevents until we have discovered all existing
+	 * tunnels and know which switches were authorized already by
+	 * the boot firmware.
+	 */
+	if (!tcm->hotplug_active)
+		dev_set_uevent_suppress(&sw->dev, true);
+
 	sw->authorized = true;
 
 	if (tb_switch_add(sw)) {
@@ -113,6 +140,9 @@ static void tb_scan_port(struct tb_port *port)
 		return;
 	}
 
+	INIT_WORK(&sw->work, tb_switch_authorize);
+	queue_work(sw->tb->wq, &sw->work);
+
 	port->remote = tb_upstream_port(sw);
 	tb_upstream_port(sw)->remote = port;
 	tb_scan_switch(sw);
@@ -149,6 +179,7 @@ static void tb_free_unplugged_children(struct tb_switch *sw)
 		if (!port->remote)
 			continue;
 		if (port->remote->sw->is_unplugged) {
+			cancel_work_sync(&port->remote->sw->work);
 			tb_switch_remove(port->remote->sw);
 			port->remote = NULL;
 		} else {
@@ -197,72 +228,58 @@ static struct tb_port *tb_find_unused_down_port(struct tb_switch *sw)
 	return NULL;
 }
 
-/**
- * tb_activate_pcie_devices() - scan for and activate PCIe devices
- *
- * This method is somewhat ad hoc. For now it only supports one device
- * per port and only devices at depth 1.
- */
-static void tb_activate_pcie_devices(struct tb *tb)
+static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
 {
-	int i;
-	int cap;
-	u32 data;
-	struct tb_switch *sw;
-	struct tb_port *up_port;
-	struct tb_port *down_port;
-	struct tb_tunnel *tunnel;
 	struct tb_cm *tcm = tb_priv(tb);
+	struct tb_switch *parent_sw;
+	struct tb_port *up, *down;
+	struct tb_tunnel *tunnel;
 
-	/* scan for pcie devices at depth 1*/
-	for (i = 1; i <= tb->root_switch->config.max_port_number; i++) {
-		if (tb_is_upstream_port(&tb->root_switch->ports[i]))
-			continue;
-		if (tb->root_switch->ports[i].config.type != TB_TYPE_PORT)
-			continue;
-		if (!tb->root_switch->ports[i].remote)
-			continue;
-		sw = tb->root_switch->ports[i].remote->sw;
-		up_port = tb_find_pci_up_port(sw);
-		if (!up_port) {
-			tb_sw_info(sw, "no PCIe devices found, aborting\n");
-			continue;
-		}
+	up = tb_find_pci_up_port(sw);
+	if (!up)
+		return 0;
 
-		/* check whether port is already activated */
-		cap = up_port->cap_adap;
-		if (!cap)
-			continue;
-		if (tb_port_read(up_port, &data, TB_CFG_PORT, cap, 1))
-			continue;
-		if (data & 0x80000000) {
-			tb_port_info(up_port,
-				     "PCIe port already activated, aborting\n");
-			continue;
-		}
+	/*
+	 * Look up available down port. Since we are chaining, it is
+	 * typically found right above this switch.
+	 */
+	down = NULL;
+	parent_sw = tb_to_switch(sw->dev.parent);
+	while (parent_sw) {
+		down = tb_find_unused_down_port(parent_sw);
+		if (down)
+			break;
+		parent_sw = tb_to_switch(parent_sw->dev.parent);
+	}
 
-		down_port = tb_find_unused_down_port(tb->root_switch);
-		if (!down_port) {
-			tb_port_info(up_port,
-				     "All PCIe down ports are occupied, aborting\n");
-			continue;
-		}
-		tunnel = tb_tunnel_alloc_pci(tb, up_port, down_port);
-		if (!tunnel) {
-			tb_port_info(up_port,
-				     "PCIe tunnel allocation failed, aborting\n");
-			continue;
-		}
+	if (!down)
+		return 0;
 
-		if (tb_tunnel_activate(tunnel)) {
-			tb_port_info(up_port,
-				     "PCIe tunnel activation failed, aborting\n");
-			tb_tunnel_free(tunnel);
-			continue;
-		}
+	tunnel = tb_tunnel_alloc_pci(tb, up, down);
+	if (!tunnel)
+		return -EIO;
 
-		list_add(&tunnel->list, &tcm->tunnel_list);
+	if (tb_tunnel_activate(tunnel)) {
+		tb_port_info(up,
+			     "PCIe tunnel activation failed, aborting\n");
+		tb_tunnel_free(tunnel);
+		return -EIO;
 	}
+	list_add_tail(&tunnel->list, &tcm->tunnel_list);
+
+	return 0;
+}
+
+static int tb_approve_switch(struct tb *tb, struct tb_switch *sw)
+{
+	/*
+	 * Already authorized by the boot firmware so no need to do
+	 * anything here.
+	 */
+	if (sw->boot)
+		return 0;
+
+	return tb_tunnel_pci(tb, sw);
 }
 
 /* hotplug handling */
@@ -316,6 +333,7 @@ static void tb_handle_hotplug(struct work_struct *work)
 			tb_port_info(port, "unplugged\n");
 			tb_sw_set_unplugged(port->remote->sw);
 			tb_free_invalid_tunnels(tb);
+			cancel_work_sync(&sw->work);
 			tb_switch_remove(port->remote->sw);
 			port->remote = NULL;
 		} else {
@@ -328,16 +346,8 @@ static void tb_handle_hotplug(struct work_struct *work)
 	} else {
 		tb_port_info(port, "hotplug: scanning\n");
 		tb_scan_port(port);
-		if (!port->remote) {
+		if (!port->remote)
 			tb_port_info(port, "hotplug: no switch found\n");
-		} else if (port->remote->sw->config.depth > 1) {
-			tb_sw_warn(port->remote->sw,
-				   "hotplug: chaining not supported\n");
-		} else {
-			tb_sw_info(port->remote->sw,
-				   "hotplug: activating pcie devices\n");
-			tb_activate_pcie_devices(tb);
-		}
 	}
 out:
 	mutex_unlock(&tb->lock);
@@ -395,6 +405,27 @@ static void tb_stop(struct tb *tb)
 	tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */
 }
 
+static int tb_scan_finalize_switch(struct device *dev, void *data)
+{
+	if (tb_is_switch(dev)) {
+		struct tb_switch *sw = tb_to_switch(dev);
+
+		/*
+		 * If we found that the switch was already setup by the
+		 * boot firmware, mark it as authorized now before we
+		 * send uevent to userspace.
+		 */
+		if (sw->boot)
+			sw->authorized = 1;
+
+		dev_set_uevent_suppress(dev, false);
+		kobject_uevent(&dev->kobj, KOBJ_ADD);
+		device_for_each_child(dev, NULL, tb_scan_finalize_switch);
+	}
+
+	return 0;
+}
+
 static int tb_start(struct tb *tb)
 {
 	struct tb_cm *tcm = tb_priv(tb);
@@ -428,7 +459,9 @@ static int tb_start(struct tb *tb)
 	tb_scan_switch(tb->root_switch);
 	/* Find out tunnels created by the boot firmware */
 	tb_discover_tunnels(tb->root_switch);
-	tb_activate_pcie_devices(tb);
+	/* Make the discovered switches available to the userspace */
+	device_for_each_child(&tb->root_switch->dev, NULL,
+			      tb_scan_finalize_switch);
 
 	/* Allow tb_handle_hotplug to progress events */
 	tcm->hotplug_active = true;
@@ -483,6 +516,7 @@ static const struct tb_cm_ops tb_cm_ops = {
 	.suspend_noirq = tb_suspend_noirq,
 	.resume_noirq = tb_resume_noirq,
 	.handle_event = tb_handle_event,
+	.approve_switch = tb_approve_switch,
 };
 
 struct tb *tb_probe(struct tb_nhi *nhi)
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH net-next v3 02/12] bnxt: Implement ndo_get_port_parent_id()
From: Jiri Pirko @ 2019-02-06 12:59 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: netdev, David S. Miller, Ido Schimmel, open list,
	open list:MELLANOX MLX5 core VPI driver,
	open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM,
	moderated list:ETHERNET BRIDGE
In-Reply-To: <20190205235326.14600-3-f.fainelli@gmail.com>

Wed, Feb 06, 2019 at 12:53:16AM CET, f.fainelli@gmail.com wrote:
>BNXT only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID, which makes it a
>great candidate to be converted to use the ndo_get_port_parent_id() NDO
>instead of implementing switchdev_port_attr_get(). The conversion is
>straight forward here since the PF and VF code use the same getter.
>
>Since bnxt makes uses of switchdev_port_same_parent_id() convert it to
>use netdev_port_same_parent_id().
>
>Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>

[...]

>diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
>index c683b5e96b1d..170d2fbbb91b 100644
>--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
>+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
>@@ -12,6 +12,7 @@
> #include <linux/if_vlan.h>
> #include <net/flow_dissector.h>
> #include <net/pkt_cls.h>
>+#include <net/switchdev.h>

You don't need this. Looks like a leftover.

Otherwise, looks fine.
Acked-by: Jiri Pirko <jiri@mellanox.com>


> #include <net/tc_act/tc_gact.h>
> #include <net/tc_act/tc_skbedit.h>
> #include <net/tc_act/tc_mirred.h>

[...]

^ permalink raw reply

* Re: [PATCH net-next v3 01/12] net: Introduce ndo_get_port_parent_id()
From: Jiri Pirko @ 2019-02-06 12:54 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: netdev, David S. Miller, Ido Schimmel, open list,
	open list:MELLANOX MLX5 core VPI driver,
	open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM,
	moderated list:ETHERNET BRIDGE
In-Reply-To: <20190205235326.14600-2-f.fainelli@gmail.com>

Wed, Feb 06, 2019 at 12:53:15AM CET, f.fainelli@gmail.com wrote:
>In preparation for getting rid of switchdev_ops, create a dedicated NDO
>operation for getting the port's parent identifier. There are
>essentially two classes of drivers that need to implement getting the
>port's parent ID which are VF/PF drivers with a built-in switch, and
>pure switchdev drivers such as mlxsw, ocelot, dsa etc.
>
>We introduce a helper function: dev_get_port_parent_id() which supports
>recursing into the lower devices to obtain the first port's parent ID.
>
>Convert the bridge, core and ipv4 multicast routing code to check for
>such ndo_get_port_parent_id() and call the helper functino when valid

s/functino/function/


>before falling back to switchdev_port_attr_get(). This will allow us to
>convert all relevant drivers in one go instead of having to implement
>both switchdev_port_attr_get() and ndo_get_port_parent_id() operations,
>then get rid of switchdev_port_attr_get().

[...]


>@@ -3651,6 +3657,9 @@ int dev_get_phys_port_id(struct net_device *dev,
> 			 struct netdev_phys_item_id *ppid);
> int dev_get_phys_port_name(struct net_device *dev,
> 			   char *name, size_t len);
>+int dev_get_port_parent_id(struct net_device *dev,
>+			   struct netdev_phys_item_id *ppid, bool recurse);
>+bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b);

One is "dev_" and the second is "netdev_". I see there is this
disconnect all over the code, but I wonder if we should not be
consistent for new things. But I don't insist. I see why both are named
differently (netdev_phys_item_id_same())

Acked-by: Jiri Pirko <jiri@mellanox.com>

^ permalink raw reply

* Re: [PATCH] MAINTAINERS: add maintainer for SFF/SFP/SFP+ support
From: Andrew Lunn @ 2019-02-06 13:03 UTC (permalink / raw)
  To: Russell King; +Cc: netdev, David S. Miller, Florian Fainelli, Heiner Kallweit
In-Reply-To: <E1grKr0-0004j4-2O@rmk-PC.armlinux.org.uk>

On Wed, Feb 06, 2019 at 10:54:54AM +0000, Russell King wrote:
> Add maintainer entry for SFF/SFP/SFP+ support.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* [PATCH net-next] cxgb4: Update 1.22.9.0 as the latest firmware supported.
From: Vishal Kulkarni @ 2019-02-06 13:01 UTC (permalink / raw)
  To: netdev, davem; +Cc: nirranjan, indranil, dt, Vishal Kulkarni

Change t4fw_version.h to update latest firmware version
number to 1.22.9.0.

Signed-off-by: Vishal Kulkarni <vishal@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
index a844296..9125ddd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
@@ -36,8 +36,8 @@
 #define __T4FW_VERSION_H__
 
 #define T4FW_VERSION_MAJOR 0x01
-#define T4FW_VERSION_MINOR 0x14
-#define T4FW_VERSION_MICRO 0x08
+#define T4FW_VERSION_MINOR 0x16
+#define T4FW_VERSION_MICRO 0x09
 #define T4FW_VERSION_BUILD 0x00
 
 #define T4FW_MIN_VERSION_MAJOR 0x01
@@ -45,8 +45,8 @@
 #define T4FW_MIN_VERSION_MICRO 0x00
 
 #define T5FW_VERSION_MAJOR 0x01
-#define T5FW_VERSION_MINOR 0x14
-#define T5FW_VERSION_MICRO 0x08
+#define T5FW_VERSION_MINOR 0x16
+#define T5FW_VERSION_MICRO 0x09
 #define T5FW_VERSION_BUILD 0x00
 
 #define T5FW_MIN_VERSION_MAJOR 0x00
@@ -54,8 +54,8 @@
 #define T5FW_MIN_VERSION_MICRO 0x00
 
 #define T6FW_VERSION_MAJOR 0x01
-#define T6FW_VERSION_MINOR 0x14
-#define T6FW_VERSION_MICRO 0x08
+#define T6FW_VERSION_MINOR 0x16
+#define T6FW_VERSION_MICRO 0x09
 #define T6FW_VERSION_BUILD 0x00
 
 #define T6FW_MIN_VERSION_MAJOR 0x00
-- 
1.8.3.1


^ permalink raw reply related

* Re: [PATCH RFC RFT net-next 00/10] Modernize mv88e6060 and remove legacy probe
From: Andrew Lunn @ 2019-02-06 12:58 UTC (permalink / raw)
  To: Gregory CLEMENT; +Cc: netdev, Vivien Didelot, Florian Fainelli, Pavel Machek
In-Reply-To: <87lg2t6tmt.fsf@FE-laptop>

> I am asking because this week the dt part can be applied to be merged in
> v5.1, whereas next week, it will be doable but as rc6 will be released
> there will be less chance to be accepted.


Hi Gregory

The DT changes can be applied anyway. They just remove disabled
nodes. I will repost that patch today, without the RFC.

       Andrew

^ permalink raw reply

* [PATCH net-next] cxgb4: Add new T6 PCI device ids 0x608b
From: Vishal Kulkarni @ 2019-02-06 12:57 UTC (permalink / raw)
  To: netdev, davem; +Cc: nirranjan, indranil, dt, Vishal Kulkarni

Signed-off-by: Vishal Kulkarni <vishal@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
index bf7325f..0c53734 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
@@ -218,6 +218,7 @@
 	CH_PCI_ID_TABLE_FENTRY(0x6088), /* Custom T62100-CR */
 	CH_PCI_ID_TABLE_FENTRY(0x6089), /* Custom T62100-KR */
 	CH_PCI_ID_TABLE_FENTRY(0x608a), /* Custom T62100-CR */
+	CH_PCI_ID_TABLE_FENTRY(0x608b), /* Custom T6225-CR */
 CH_PCI_DEVICE_ID_TABLE_DEFINE_END;
 
 #endif /* __T4_PCI_ID_TBL_H__ */
-- 
1.8.3.1


^ permalink raw reply related

* Re: [net-next, PATCH] net: stmmac: fix ptp timestamping on Rx on gmac4
From: Alexandre Torgue @ 2019-02-06 12:56 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: peppe.cavallaro, davem, mcoquelin.stm32, netdev, joabreu
In-Reply-To: <1549368920-1989-1-git-send-email-ilias.apalodimas@linaro.org>

Hi Ilias

On 2/5/19 1:15 PM, Ilias Apalodimas wrote:
> The current driver only enables Pdelay_Req and Pdelay_Resp when
> HWTSTAMP_FILTER_PTP_V2_EVENT, HWTSTAMP_FILTER_PTP_V1_L4_EVENT or
> HWTSTAMP_FILTER_PTP_V2_L4_EVENT is requested. This results in ptp sync on
> slave mode to report 'received SYNC without timestamp' when using ptp4l.
> 
> Although the hardware can support Sync, Pdelay_Req and Pdelay_resp by
> setting bit14 annd bits 17/16 to 01 this leaves Delay_Req timestamps out.
> 
> Fix this by enabling all event and general messages timestamps.
> This includes SYNC, Follow_Up, Delay_Req, Delay_Resp, Pdelay_Req,
> Pdelay_Resp and Pdelay_Resp_Follow_Up messages.
> 
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

For GMAC4 part:

Tested-by: Alexandre TORGUE <alexandre.torgue@st.com>

^ permalink raw reply

* [PATCH net 2/2] sit: check if IPv6 enabled before call ip6_err_gen_icmpv6_unreach()
From: Hangbin Liu @ 2019-02-06 12:51 UTC (permalink / raw)
  To: netdev; +Cc: Stefano Brivio, David Miller, Hangbin Liu
In-Reply-To: <20190206125111.5286-1-liuhangbin@gmail.com>

If we disabled IPv6 from kernel boot up cmd(ipv6.disable=1), we should not
call ip6_err_gen_icmpv6_unreach().

Reproducer:
ip link add sit1 type sit local 10.10.0.1 remote 10.10.1.1 ttl 1
ip link set sit1 up
ip addr add 192.168.0.1/24 dev sit1
ping 192.168.0.2

Reported-by: Jianlin Shi <jishi@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 net/ipv6/sit.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1e03305c0549..e43fbac0fd1a 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -493,6 +493,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
 	const int type = icmp_hdr(skb)->type;
 	const int code = icmp_hdr(skb)->code;
 	unsigned int data_len = 0;
+	struct inet6_dev *idev;
 	struct ip_tunnel *t;
 	int sifindex;
 	int err;
@@ -546,8 +547,13 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
 	}
 
 	err = 0;
-	if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
+
+	idev = in6_dev_get(skb->dev);
+	if (idev &&
+	    !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len)) {
+		in6_dev_put(idev);
 		goto out;
+	}
 
 	if (t->parms.iph.daddr == 0)
 		goto out;
-- 
2.19.2


^ permalink raw reply related

* [PATCH net 1/2] geneve: should not call rt6_lookup() when ipv6 was disabled
From: Hangbin Liu @ 2019-02-06 12:51 UTC (permalink / raw)
  To: netdev; +Cc: Stefano Brivio, David Miller, Hangbin Liu
In-Reply-To: <20190206125111.5286-1-liuhangbin@gmail.com>

When we add a new GENEVE device with IPv6 remote, checking only for
IS_ENABLED(CONFIG_IPV6) is not enough as we may disable IPv6 in kernel
cmd(ipv6.disable=1), which will cause a NULL pointer dereference.

Reported-by: Jianlin Shi <jishi@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 drivers/net/geneve.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 58bbba8582b0..0658715581e3 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1512,6 +1512,10 @@ static void geneve_link_config(struct net_device *dev,
 	}
 #if IS_ENABLED(CONFIG_IPV6)
 	case AF_INET6: {
+		struct inet6_dev *idev = in6_dev_get(dev);
+		if (!idev)
+			break;
+
 		struct rt6_info *rt = rt6_lookup(geneve->net,
 						 &info->key.u.ipv6.dst, NULL, 0,
 						 NULL, 0);
@@ -1519,6 +1523,8 @@ static void geneve_link_config(struct net_device *dev,
 		if (rt && rt->dst.dev)
 			ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
 		ip6_rt_put(rt);
+
+		in6_dev_put(idev);
 		break;
 	}
 #endif
-- 
2.19.2


^ permalink raw reply related

* [PATCH net 0/2] fix two kernel panics when disabled IPv6 on boot up
From: Hangbin Liu @ 2019-02-06 12:51 UTC (permalink / raw)
  To: netdev; +Cc: Stefano Brivio, David Miller, Hangbin Liu

When disabled IPv6 on boot up, since there is no ipv6 route tables, we should
not call rt6_lookup. Fix them by checking if we have inet6_dev pointer on
netdevice.

Hangbin Liu (2):
  geneve: should not call rt6_lookup() when ipv6 was disabled
  sit: check if IPv6 enabled before call ip6_err_gen_icmpv6_unreach()

 drivers/net/geneve.c | 6 ++++++
 net/ipv6/sit.c       | 8 +++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

-- 
2.19.2


^ permalink raw reply

* Re: [PATCH v2 3/6] ethtool: introduce new ioctl for per-queue settings
From: Michal Kubecek @ 2019-02-06 12:43 UTC (permalink / raw)
  To: netdev; +Cc: Jeff Kirsher, linville, Nicholas Nunley, nhorman, sassmann
In-Reply-To: <20190206000106.24364-3-jeffrey.t.kirsher@intel.com>

On Tue, Feb 05, 2019 at 04:01:03PM -0800, Jeff Kirsher wrote:
> +static int do_perqueue(struct cmd_context *ctx)
> +{
> +	__u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)] = {0};
> +	int i, n_queues = 0;
> +
> +	if (ctx->argc == 0)
> +		exit_bad_args();
> +
> +	/*
> +	 * The sub commands will be applied to
> +	 * all queues if no queue_mask set
> +	 */
> +	if (strncmp(*ctx->argp, "queue_mask", 10)) {

This would match any string starting with "queue_mask", is it intended? 

> +		n_queues = find_max_num_queues(ctx);
> +		if (n_queues < 0) {
> +			perror("Cannot get number of queues");
> +			return -EFAULT;
> +		}
> +		for (i = 0; i < n_queues / 32; i++)
> +			queue_mask[i] = ~0;
> +		queue_mask[i] = (1 << (n_queues - i * 32)) - 1;

It's unlikely today, I guess, but in theory, this would overflow if
n_queues == MAX_NUM_QUEUE

> +		fprintf(stdout,
> +			"The sub commands will be applied to all %d queues\n",
> +			n_queues);
> +	} else {
> +		ctx->argc--;
> +		ctx->argp++;
> +		n_queues = set_queue_mask(queue_mask, *ctx->argp);
> +		if (n_queues < 0) {
> +			perror("Invalid queue mask");
> +			return n_queues;
> +		}
> +		ctx->argc--;
> +		ctx->argp++;
> +	}
> +
> +	i = find_option(ctx->argc, ctx->argp);
> +	if (i < 0)
> +		exit_bad_args();
> +
> +	/* no sub_command support yet */
> +
> +	return 0;
> +}

Michal Kubecek

^ permalink raw reply

* Re: [PATCH v3 2/2] r8169: Avoid pointer aliasing
From: Thierry Reding @ 2019-02-06 12:35 UTC (permalink / raw)
  To: David S. Miller
  Cc: Heiner Kallweit, Andrew Lunn, Joe Perches, Eric Dumazet,
	Paul Zimmerman, Michal Kubecek, Realtek linux nic maintainers,
	netdev, linux-kernel
In-Reply-To: <20190206123018.24802-2-thierry.reding@gmail.com>

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

On Wed, Feb 06, 2019 at 01:30:18PM +0100, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Read MAC address 32-bit at a time and manually extract the individual
> bytes. This avoids pointer aliasing and gives the compiler a better
> chance of optimizing the operation.
> 
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Applies to net-next.
> 
> I tested this on a Jetson TX2 with an add-in Realtek ethernet card that
> has a properly programmed OTP to verify that I got the endianess right.
> Seems like everything works and the device behaves the same with or
> without this patch.
> 
> Changes in v3:
> - align MAC address to u16 for is_valid_ether_addr()
> 
>  drivers/net/ethernet/realtek/r8169.c | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)

I also forgot Andrew's Reviewed-by here, but technically the patch has
changed, so I'll leave it up to him to confirm he's still okay with this
version.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v3 1/2] r8169: Load MAC address from device tree if present
From: Thierry Reding @ 2019-02-06 12:33 UTC (permalink / raw)
  To: David S. Miller
  Cc: Heiner Kallweit, Andrew Lunn, Joe Perches, Eric Dumazet,
	Paul Zimmerman, Michal Kubecek, Realtek linux nic maintainers,
	netdev, linux-kernel
In-Reply-To: <20190206123018.24802-1-thierry.reding@gmail.com>

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

On Wed, Feb 06, 2019 at 01:30:17PM +0100, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> If the system was booted using a device tree and if the device tree
> contains a MAC address, use it instead of reading one from the EEPROM.
> This is useful in situations where the EEPROM isn't properly programmed
> or where the firmware wants to override the existing MAC address.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Applies on net-next.
> 
> Changes in v2:
> - rewrite error check for readability
> - initialize mac_addr array
> 
>  drivers/net/ethernet/realtek/r8169.c | 36 ++++++++++++++++++----------
>  1 file changed, 23 insertions(+), 13 deletions(-)

Sorry, I forgot to include Heiner's Reviewed-by tag here, but with any
luck patchwork will pick it up if I do this:

This patch previously:

Reviewed-by: Heiner Kallweit <hkallweit1@gmail.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [PATCH v3 1/2] r8169: Load MAC address from device tree if present
From: Thierry Reding @ 2019-02-06 12:30 UTC (permalink / raw)
  To: David S. Miller
  Cc: Heiner Kallweit, Andrew Lunn, Joe Perches, Eric Dumazet,
	Paul Zimmerman, Michal Kubecek, Realtek linux nic maintainers,
	netdev, linux-kernel

From: Thierry Reding <treding@nvidia.com>

If the system was booted using a device tree and if the device tree
contains a MAC address, use it instead of reading one from the EEPROM.
This is useful in situations where the EEPROM isn't properly programmed
or where the firmware wants to override the existing MAC address.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Applies on net-next.

Changes in v2:
- rewrite error check for readability
- initialize mac_addr array

 drivers/net/ethernet/realtek/r8169.c | 36 ++++++++++++++++++----------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index e8a112149a62..501891be7c56 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7110,6 +7110,21 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
 	return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
 }
 
+static void rtl_read_mac_address(struct rtl8169_private *tp,
+				 u8 mac_addr[ETH_ALEN])
+{
+	/* Get MAC address */
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38:
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+		*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
+		*(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);
+		break;
+	default:
+		break;
+	}
+}
+
 DECLARE_RTL_COND(rtl_link_list_ready_cond)
 {
 	return RTL_R8(tp, MCU) & LINK_LIST_RDY;
@@ -7301,6 +7316,7 @@ static int rtl_get_ether_clk(struct rtl8169_private *tp)
 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+	u8 mac_addr[ETH_ALEN] __aligned(4) = {};
 	struct rtl8169_private *tp;
 	struct net_device *dev;
 	int chipset, region, i;
@@ -7403,20 +7419,14 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	u64_stats_init(&tp->rx_stats.syncp);
 	u64_stats_init(&tp->tx_stats.syncp);
 
-	/* Get MAC address */
-	switch (tp->mac_version) {
-		u8 mac_addr[ETH_ALEN] __aligned(4);
-	case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38:
-	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
-		*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
-		*(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);
+	/* get MAC address */
+	rc = eth_platform_get_mac_address(&pdev->dev, mac_addr);
+	if (rc)
+		rtl_read_mac_address(tp, mac_addr);
+
+	if (is_valid_ether_addr(mac_addr))
+		rtl_rar_set(tp, mac_addr);
 
-		if (is_valid_ether_addr(mac_addr))
-			rtl_rar_set(tp, mac_addr);
-		break;
-	default:
-		break;
-	}
 	for (i = 0; i < ETH_ALEN; i++)
 		dev->dev_addr[i] = RTL_R8(tp, MAC0 + i);
 
-- 
2.19.1


^ permalink raw reply related

* [PATCH v3 2/2] r8169: Avoid pointer aliasing
From: Thierry Reding @ 2019-02-06 12:30 UTC (permalink / raw)
  To: David S. Miller
  Cc: Heiner Kallweit, Andrew Lunn, Joe Perches, Eric Dumazet,
	Paul Zimmerman, Michal Kubecek, Realtek linux nic maintainers,
	netdev, linux-kernel
In-Reply-To: <20190206123018.24802-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

Read MAC address 32-bit at a time and manually extract the individual
bytes. This avoids pointer aliasing and gives the compiler a better
chance of optimizing the operation.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Applies to net-next.

I tested this on a Jetson TX2 with an add-in Realtek ethernet card that
has a properly programmed OTP to verify that I got the endianess right.
Seems like everything works and the device behaves the same with or
without this patch.

Changes in v3:
- align MAC address to u16 for is_valid_ether_addr()

 drivers/net/ethernet/realtek/r8169.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 501891be7c56..1dd72137fd53 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7113,12 +7113,21 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
 static void rtl_read_mac_address(struct rtl8169_private *tp,
 				 u8 mac_addr[ETH_ALEN])
 {
+	u32 value;
+
 	/* Get MAC address */
 	switch (tp->mac_version) {
 	case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38:
 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
-		*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
-		*(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);
+		value = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
+		mac_addr[0] = (value >>  0) & 0xff;
+		mac_addr[1] = (value >>  8) & 0xff;
+		mac_addr[2] = (value >> 16) & 0xff;
+		mac_addr[3] = (value >> 24) & 0xff;
+
+		value = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);
+		mac_addr[4] = (value >>  0) & 0xff;
+		mac_addr[5] = (value >>  8) & 0xff;
 		break;
 	default:
 		break;
@@ -7316,7 +7325,8 @@ static int rtl_get_ether_clk(struct rtl8169_private *tp)
 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
-	u8 mac_addr[ETH_ALEN] __aligned(4) = {};
+	/* align to u16 for is_valid_ether_addr() */
+	u8 mac_addr[ETH_ALEN] __aligned(2) = {};
 	struct rtl8169_private *tp;
 	struct net_device *dev;
 	int chipset, region, i;
-- 
2.19.1


^ permalink raw reply related

* Re: [Patch net-next] mlx5: use RCU lock in mlx5_eq_cq_get()
From: Tariq Toukan @ 2019-02-06 12:02 UTC (permalink / raw)
  To: Cong Wang, netdev@vger.kernel.org; +Cc: Saeed Mahameed
In-Reply-To: <20190206003525.5041-1-xiyou.wangcong@gmail.com>



On 2/6/2019 2:35 AM, Cong Wang wrote:
> mlx5_eq_cq_get() is called in IRQ handler, the spinlock inside
> gets a lot of contentions when we test some heavy workload
> with 60 RX queues and 80 CPU's, and it is clearly shown in the
> flame graph.
> 
> In fact, radix_tree_lookup() is perfectly fine with RCU read lock,
> we don't have to take a spinlock on this hot path. It is pretty much
> similar to commit 291c566a2891
> ("net/mlx4_core: Fix racy CQ (Completion Queue) free"). Slow paths
> are still serialized with the spinlock, and with synchronize_irq()
> it should be safe to just move the fast path to RCU read lock.
> 
> This patch itself reduces the latency by about 50% with our workload.
> 
> Cc: Saeed Mahameed <saeedm@mellanox.com>
> Cc: Tariq Toukan <tariqt@mellanox.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
>   drivers/net/ethernet/mellanox/mlx5/core/eq.c | 12 ++++++------
>   1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> index ee04aab65a9f..7092457705a2 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> @@ -114,11 +114,11 @@ static struct mlx5_core_cq *mlx5_eq_cq_get(struct mlx5_eq *eq, u32 cqn)
>   	struct mlx5_cq_table *table = &eq->cq_table;
>   	struct mlx5_core_cq *cq = NULL;
>   
> -	spin_lock(&table->lock);
> +	rcu_read_lock();
>   	cq = radix_tree_lookup(&table->tree, cqn);
>   	if (likely(cq))
>   		mlx5_cq_hold(cq);
> -	spin_unlock(&table->lock);
> +	rcu_read_unlock();

Thanks for you patch.

I think we can improve it further, by taking the if statement out of the 
critical section.

Other than that, patch LGTM.

Regards,
Tariq

>   
>   	return cq;
>   }
> @@ -371,9 +371,9 @@ int mlx5_eq_add_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq)
>   	struct mlx5_cq_table *table = &eq->cq_table;
>   	int err;
>   
> -	spin_lock_irq(&table->lock);
> +	spin_lock(&table->lock);
>   	err = radix_tree_insert(&table->tree, cq->cqn, cq);
> -	spin_unlock_irq(&table->lock);
> +	spin_unlock(&table->lock);
>   
>   	return err;
>   }
> @@ -383,9 +383,9 @@ int mlx5_eq_del_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq)
>   	struct mlx5_cq_table *table = &eq->cq_table;
>   	struct mlx5_core_cq *tmp;
>   
> -	spin_lock_irq(&table->lock);
> +	spin_lock(&table->lock);
>   	tmp = radix_tree_delete(&table->tree, cq->cqn);
> -	spin_unlock_irq(&table->lock);
> +	spin_unlock(&table->lock);
>   
>   	if (!tmp) {
>   		mlx5_core_warn(eq->dev, "cq 0x%x not found in eq 0x%x tree\n", eq->eqn, cq->cqn);
> 

^ permalink raw reply

* Re: [PATCH net-next v5 11/12] socket: Rename SO_RCVTIMEO/ SO_SNDTIMEO with _OLD suffixes
From: Michael Ellerman @ 2019-02-06 11:58 UTC (permalink / raw)
  To: Deepa Dinamani, davem, linux-kernel
  Cc: netdev, arnd, y2038, ccaulfie, deller, paulus, ralf, rth,
	cluster-devel, linuxppc-dev, linux-alpha, linux-arch, linux-mips,
	linux-parisc, sparclinux
In-Reply-To: <20190202153454.7121-12-deepa.kernel@gmail.com>

Deepa Dinamani <deepa.kernel@gmail.com> writes:

> SO_RCVTIMEO and SO_SNDTIMEO socket options use struct timeval
> as the time format. struct timeval is not y2038 safe.
> The subsequent patches in the series add support for new socket
> timeout options with _NEW suffix that will use y2038 safe
> data structures. Although the existing struct timeval layout
> is sufficiently wide to represent timeouts, because of the way
> libc will interpret time_t based on user defined flag, these
> new flags provide a way of having a structure that is the same
> for all architectures consistently.
> Rename the existing options with _OLD suffix forms so that the
> right option is enabled for userspace applications according
> to the architecture and time_t definition of libc.
>
> Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
> Acked-by: Willem de Bruijn <willemb@google.com>
> Cc: ccaulfie@redhat.com
> Cc: deller@gmx.de
> Cc: paulus@samba.org
> Cc: ralf@linux-mips.org
> Cc: rth@twiddle.net
> Cc: cluster-devel@redhat.com
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-alpha@vger.kernel.org
> Cc: linux-arch@vger.kernel.org
> Cc: linux-mips@vger.kernel.org
> Cc: linux-parisc@vger.kernel.org
> Cc: sparclinux@vger.kernel.org
> ---
>  arch/alpha/include/uapi/asm/socket.h   | 7 +++++--
>  arch/mips/include/uapi/asm/socket.h    | 6 ++++--
>  arch/parisc/include/uapi/asm/socket.h  | 6 ++++--
>  arch/powerpc/include/uapi/asm/socket.h | 4 ++--

The powerpc changes look OK to me.

Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)

cheers

> diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
> index 94de465e0920..12aa0c43e775 100644
> --- a/arch/powerpc/include/uapi/asm/socket.h
> +++ b/arch/powerpc/include/uapi/asm/socket.h
> @@ -11,8 +11,8 @@
>  
>  #define SO_RCVLOWAT	16
>  #define SO_SNDLOWAT	17
> -#define SO_RCVTIMEO	18
> -#define SO_SNDTIMEO	19
> +#define SO_RCVTIMEO_OLD	18
> +#define SO_SNDTIMEO_OLD	19
>  #define SO_PASSCRED	20
>  #define SO_PEERCRED	21
>  
> diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
> index 2713e0fa68ef..c56b8b487c12 100644
> --- a/include/uapi/asm-generic/socket.h
> +++ b/include/uapi/asm-generic/socket.h
> @@ -30,8 +30,8 @@
>  #define SO_PEERCRED	17
>  #define SO_RCVLOWAT	18
>  #define SO_SNDLOWAT	19
> -#define SO_RCVTIMEO	20
> -#define SO_SNDTIMEO	21
> +#define SO_RCVTIMEO_OLD	20
> +#define SO_SNDTIMEO_OLD	21
>  #endif
>  
>  /* Security levels - as per NRL IPv6 - don't actually do anything */
> @@ -116,6 +116,8 @@
>  
>  #if !defined(__KERNEL__)
>  
> +#define	SO_RCVTIMEO SO_RCVTIMEO_OLD
> +#define	SO_SNDTIMEO SO_SNDTIMEO_OLD
>  #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
>  /* on 64-bit and x32, avoid the ?: operator */
>  #define SO_TIMESTAMP		SO_TIMESTAMP_OLD

^ permalink raw reply

* Re: [PATCH net-next v5 12/12] sock: Add SO_RCVTIMEO_NEW and SO_SNDTIMEO_NEW
From: Michael Ellerman @ 2019-02-06 11:56 UTC (permalink / raw)
  To: Deepa Dinamani, davem, linux-kernel
  Cc: netdev, arnd, y2038, ccaulfie, deller, paulus, ralf, rth,
	cluster-devel, linuxppc-dev, linux-alpha, linux-arch, linux-mips,
	linux-parisc, sparclinux
In-Reply-To: <20190202153454.7121-13-deepa.kernel@gmail.com>

Deepa Dinamani <deepa.kernel@gmail.com> writes:

> Add new socket timeout options that are y2038 safe.
>
> Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
> Acked-by: Willem de Bruijn <willemb@google.com>
> Cc: ccaulfie@redhat.com
> Cc: davem@davemloft.net
> Cc: deller@gmx.de
> Cc: paulus@samba.org
> Cc: ralf@linux-mips.org
> Cc: rth@twiddle.net
> Cc: cluster-devel@redhat.com
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-alpha@vger.kernel.org
> Cc: linux-arch@vger.kernel.org
> Cc: linux-mips@vger.kernel.org
> Cc: linux-parisc@vger.kernel.org
> Cc: sparclinux@vger.kernel.org
> ---
>  arch/alpha/include/uapi/asm/socket.h  | 12 ++++--
>  arch/mips/include/uapi/asm/socket.h   | 11 +++++-
>  arch/parisc/include/uapi/asm/socket.h | 10 ++++-
>  arch/sparc/include/uapi/asm/socket.h  | 11 +++++-

You touched powerpc in the previous patch but not this one.

That's because we use the asm-generic version I assume. Would be good to
mention in the change log though to avoid any confusion.

cheers

>  include/uapi/asm-generic/socket.h     | 11 +++++-
>  net/core/sock.c                       | 53 ++++++++++++++++++++-------
>  6 files changed, 83 insertions(+), 25 deletions(-)
>
> diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
> index 9826d1db71d0..0d0fddb7e738 100644
> --- a/arch/alpha/include/uapi/asm/socket.h
> +++ b/arch/alpha/include/uapi/asm/socket.h
> @@ -119,19 +119,25 @@
>  #define SO_TIMESTAMPNS_NEW      64
>  #define SO_TIMESTAMPING_NEW     65
>  
> -#if !defined(__KERNEL__)
> +#define SO_RCVTIMEO_NEW         66
> +#define SO_SNDTIMEO_NEW         67
>  
> -#define	SO_RCVTIMEO SO_RCVTIMEO_OLD
> -#define	SO_SNDTIMEO SO_SNDTIMEO_OLD
> +#if !defined(__KERNEL__)
>  
>  #if __BITS_PER_LONG == 64
>  #define SO_TIMESTAMP		SO_TIMESTAMP_OLD
>  #define SO_TIMESTAMPNS		SO_TIMESTAMPNS_OLD
>  #define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
> +
> +#define SO_RCVTIMEO		SO_RCVTIMEO_OLD
> +#define SO_SNDTIMEO		SO_SNDTIMEO_OLD
>  #else
>  #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
>  #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
>  #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
> +
> +#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
> +#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
>  #endif
>  
>  #define SCM_TIMESTAMP           SO_TIMESTAMP
> diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
> index 96cc0e907f12..eb9f33f8a8b3 100644
> --- a/arch/mips/include/uapi/asm/socket.h
> +++ b/arch/mips/include/uapi/asm/socket.h
> @@ -130,18 +130,25 @@
>  #define SO_TIMESTAMPNS_NEW      64
>  #define SO_TIMESTAMPING_NEW     65
>  
> +#define SO_RCVTIMEO_NEW         66
> +#define SO_SNDTIMEO_NEW         67
> +
>  #if !defined(__KERNEL__)
>  
> -#define	SO_RCVTIMEO SO_RCVTIMEO_OLD
> -#define	SO_SNDTIMEO SO_SNDTIMEO_OLD
>  #if __BITS_PER_LONG == 64
>  #define SO_TIMESTAMP		SO_TIMESTAMP_OLD
>  #define SO_TIMESTAMPNS		SO_TIMESTAMPNS_OLD
>  #define SO_TIMESTAMPING		SO_TIMESTAMPING_OLD
> +
> +#define SO_RCVTIMEO             SO_RCVTIMEO_OLD
> +#define SO_SNDTIMEO             SO_SNDTIMEO_OLD
>  #else
>  #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
>  #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
>  #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
> +
> +#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
> +#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
>  #endif
>  
>  #define SCM_TIMESTAMP           SO_TIMESTAMP
> diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
> index 046f0cd9cce4..16e428f03526 100644
> --- a/arch/parisc/include/uapi/asm/socket.h
> +++ b/arch/parisc/include/uapi/asm/socket.h
> @@ -111,18 +111,24 @@
>  #define SO_TIMESTAMPNS_NEW      0x4039
>  #define SO_TIMESTAMPING_NEW     0x403A
>  
> +#define SO_RCVTIMEO_NEW         0x4040
> +#define SO_SNDTIMEO_NEW         0x4041
> +
>  #if !defined(__KERNEL__)
>  
> -#define	SO_RCVTIMEO SO_RCVTIMEO_OLD
> -#define	SO_SNDTIMEO SO_SNDTIMEO_OLD
>  #if __BITS_PER_LONG == 64
>  #define SO_TIMESTAMP		SO_TIMESTAMP_OLD
>  #define SO_TIMESTAMPNS		SO_TIMESTAMPNS_OLD
>  #define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
> +#define SO_RCVTIMEO		SO_RCVTIMEO_OLD
> +#define SO_SNDTIMEO		SO_SNDTIMEO_OLD
>  #else
>  #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
>  #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
>  #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
> +
> +#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
> +#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
>  #endif
>  
>  #define SCM_TIMESTAMP           SO_TIMESTAMP
> diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
> index 342ffdc3b424..8c9f74a66b55 100644
> --- a/arch/sparc/include/uapi/asm/socket.h
> +++ b/arch/sparc/include/uapi/asm/socket.h
> @@ -112,19 +112,26 @@
>  #define SO_TIMESTAMPNS_NEW       0x0042
>  #define SO_TIMESTAMPING_NEW      0x0043
>  
> +#define SO_RCVTIMEO_NEW          0x0044
> +#define SO_SNDTIMEO_NEW          0x0045
> +
>  #if !defined(__KERNEL__)
>  
> -#define SO_RCVTIMEO              SO_RCVTIMEO_OLD
> -#define SO_SNDTIMEO              SO_SNDTIMEO_OLD
>  
>  #if __BITS_PER_LONG == 64
>  #define SO_TIMESTAMP		SO_TIMESTAMP_OLD
>  #define SO_TIMESTAMPNS		SO_TIMESTAMPNS_OLD
>  #define SO_TIMESTAMPING		SO_TIMESTAMPING_OLD
> +
> +#define SO_RCVTIMEO		SO_RCVTIMEO_OLD
> +#define SO_SNDTIMEO		SO_SNDTIMEO_OLD
>  #else
>  #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
>  #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
>  #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
> +
> +#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
> +#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
>  #endif
>  
>  #define SCM_TIMESTAMP          SO_TIMESTAMP
> diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
> index c56b8b487c12..c8b430cb6dc4 100644
> --- a/include/uapi/asm-generic/socket.h
> +++ b/include/uapi/asm-generic/socket.h
> @@ -114,19 +114,26 @@
>  #define SO_TIMESTAMPNS_NEW      64
>  #define SO_TIMESTAMPING_NEW     65
>  
> +#define SO_RCVTIMEO_NEW         66
> +#define SO_SNDTIMEO_NEW         67
> +
>  #if !defined(__KERNEL__)
>  
> -#define	SO_RCVTIMEO SO_RCVTIMEO_OLD
> -#define	SO_SNDTIMEO SO_SNDTIMEO_OLD
>  #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
>  /* on 64-bit and x32, avoid the ?: operator */
>  #define SO_TIMESTAMP		SO_TIMESTAMP_OLD
>  #define SO_TIMESTAMPNS		SO_TIMESTAMPNS_OLD
>  #define SO_TIMESTAMPING		SO_TIMESTAMPING_OLD
> +
> +#define SO_RCVTIMEO		SO_RCVTIMEO_OLD
> +#define SO_SNDTIMEO		SO_SNDTIMEO_OLD
>  #else
>  #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
>  #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
>  #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
> +
> +#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
> +#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
>  #endif
>  
>  #define SCM_TIMESTAMP           SO_TIMESTAMP
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 27b40002b780..a8904ae40713 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -335,9 +335,10 @@ int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
>  }
>  EXPORT_SYMBOL(__sk_backlog_rcv);
>  
> -static int sock_get_timeout(long timeo, void *optval)
> +static int sock_get_timeout(long timeo, void *optval, bool old_timeval)
>  {
> -	struct __kernel_old_timeval tv;
> +	struct __kernel_sock_timeval tv;
> +	int size;
>  
>  	if (timeo == MAX_SCHEDULE_TIMEOUT) {
>  		tv.tv_sec = 0;
> @@ -353,13 +354,23 @@ static int sock_get_timeout(long timeo, void *optval)
>  		return sizeof(tv32);
>  	}
>  
> -	*(struct __kernel_old_timeval *)optval = tv;
> -	return sizeof(tv);
> +	if (old_timeval) {
> +		struct __kernel_old_timeval old_tv;
> +		old_tv.tv_sec = tv.tv_sec;
> +		old_tv.tv_usec = tv.tv_usec;
> +		*(struct __kernel_old_timeval *)optval = old_tv;
> +		size = sizeof(old_tv);
> +	} else {
> +		*(struct __kernel_sock_timeval *)optval = tv;
> +		size = sizeof(tv);
> +	}
> +
> +	return size;
>  }
>  
> -static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
> +static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen, bool old_timeval)
>  {
> -	struct __kernel_old_timeval tv;
> +	struct __kernel_sock_timeval tv;
>  
>  	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
>  		struct old_timeval32 tv32;
> @@ -371,6 +382,15 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
>  			return -EFAULT;
>  		tv.tv_sec = tv32.tv_sec;
>  		tv.tv_usec = tv32.tv_usec;
> +	} else if (old_timeval) {
> +		struct __kernel_old_timeval old_tv;
> +
> +		if (optlen < sizeof(old_tv))
> +			return -EINVAL;
> +		if (copy_from_user(&old_tv, optval, sizeof(old_tv)))
> +			return -EFAULT;
> +		tv.tv_sec = old_tv.tv_sec;
> +		tv.tv_usec = old_tv.tv_usec;
>  	} else {
>  		if (optlen < sizeof(tv))
>  			return -EINVAL;
> @@ -394,8 +414,8 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
>  	*timeo_p = MAX_SCHEDULE_TIMEOUT;
>  	if (tv.tv_sec == 0 && tv.tv_usec == 0)
>  		return 0;
> -	if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT/HZ - 1))
> -		*timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP(tv.tv_usec, USEC_PER_SEC / HZ);
> +	if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))
> +		*timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, USEC_PER_SEC / HZ);
>  	return 0;
>  }
>  
> @@ -942,11 +962,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
>  		break;
>  
>  	case SO_RCVTIMEO_OLD:
> -		ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen);
> +	case SO_RCVTIMEO_NEW:
> +		ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen, optname == SO_RCVTIMEO_OLD);
>  		break;
>  
>  	case SO_SNDTIMEO_OLD:
> -		ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen);
> +	case SO_SNDTIMEO_NEW:
> +		ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen, optname == SO_SNDTIMEO_OLD);
>  		break;
>  
>  	case SO_ATTACH_FILTER:
> @@ -1171,6 +1193,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
>  		struct linger ling;
>  		struct old_timeval32 tm32;
>  		struct __kernel_old_timeval tm;
> +		struct  __kernel_sock_timeval stm;
>  		struct sock_txtime txtime;
>  	} v;
>  
> @@ -1279,12 +1302,14 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
>  		v.val = sk->sk_tsflags;
>  		break;
>  
> -	case SO_RCVTIMEO:
> -		lv = sock_get_timeout(sk->sk_rcvtimeo, &v);
> +	case SO_RCVTIMEO_OLD:
> +	case SO_RCVTIMEO_NEW:
> +		lv = sock_get_timeout(sk->sk_rcvtimeo, &v, SO_RCVTIMEO_OLD == optname);
>  		break;
>  
> -	case SO_SNDTIMEO:
> -		lv = sock_get_timeout(sk->sk_sndtimeo, &v);
> +	case SO_SNDTIMEO_OLD:
> +	case SO_SNDTIMEO_NEW:
> +		lv = sock_get_timeout(sk->sk_sndtimeo, &v, SO_SNDTIMEO_OLD == optname);
>  		break;
>  
>  	case SO_RCVLOWAT:
> -- 
> 2.17.1

^ permalink raw reply

* Re: [net-next, PATCH] net: stmmac: fix ptp timestamping on Rx on gmac4
From: Jose Abreu @ 2019-02-06 11:45 UTC (permalink / raw)
  To: Ilias Apalodimas, alexandre.torgue
  Cc: peppe.cavallaro, davem, mcoquelin.stm32, netdev, jose.abreu
In-Reply-To: <1549368920-1989-1-git-send-email-ilias.apalodimas@linaro.org>

On 2/5/2019 12:15 PM, Ilias Apalodimas wrote:
> The current driver only enables Pdelay_Req and Pdelay_Resp when
> HWTSTAMP_FILTER_PTP_V2_EVENT, HWTSTAMP_FILTER_PTP_V1_L4_EVENT or
> HWTSTAMP_FILTER_PTP_V2_L4_EVENT is requested. This results in ptp sync on
> slave mode to report 'received SYNC without timestamp' when using ptp4l.
> 
> Although the hardware can support Sync, Pdelay_Req and Pdelay_resp by
> setting bit14 annd bits 17/16 to 01 this leaves Delay_Req timestamps out.
> 
> Fix this by enabling all event and general messages timestamps.
> This includes SYNC, Follow_Up, Delay_Req, Delay_Resp, Pdelay_Req,
> Pdelay_Resp and Pdelay_Resp_Follow_Up messages.
> 
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

Acked-by: Jose Abreu <joabreu@synopsys.com>

and, on XGMAC2: Tested-by: Jose Abreu <joabreu@synopsys.com>

Thanks,
Jose Miguel Abreu

^ permalink raw reply

* [PATCH net-next 6/6] ARM: dts: clearfog: add comphy settings for Ethernet interfaces
From: Russell King @ 2019-02-06 11:35 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Jason Cooper,
	Kishon Vijay Abraham I, Sebastian Hesselbarth, Thomas Petazzoni
  Cc: devicetree, linux-arm-kernel, netdev, Rob Herring, Mark Rutland
In-Reply-To: <20190206113409.ko7lwuv5kb7l7rjo@shell.armlinux.org.uk>

Add the comphy settings for the Ethernet interfaces.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/boot/dts/armada-388-clearfog.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/armada-388-clearfog.dtsi b/arch/arm/boot/dts/armada-388-clearfog.dtsi
index 1b0d0680c8b6..0d81600ca247 100644
--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi
+++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi
@@ -93,6 +93,7 @@
 	bm,pool-long = <2>;
 	bm,pool-short = <1>;
 	buffer-manager = <&bm>;
+	phys = <&comphy1 1>;
 	phy-mode = "sgmii";
 	status = "okay";
 };
@@ -103,6 +104,7 @@
 	bm,pool-short = <1>;
 	buffer-manager = <&bm>;
 	managed = "in-band-status";
+	phys = <&comphy5 2>;
 	phy-mode = "sgmii";
 	sfp = <&sfp>;
 	status = "okay";
-- 
2.7.4


^ permalink raw reply related

* [PATCH net-next 5/6] net: marvell: neta: add comphy support
From: Russell King @ 2019-02-06 11:35 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Jason Cooper,
	Kishon Vijay Abraham I, Sebastian Hesselbarth, Thomas Petazzoni
  Cc: devicetree, linux-arm-kernel, netdev, David S. Miller
In-Reply-To: <20190206113409.ko7lwuv5kb7l7rjo@shell.armlinux.org.uk>

Add support for the common phy binding, so that we can reconfigure the
comphy according to the desired ethernet speed.  This will allow us to
support 1000base-X and 2500base-X SFPs dynamically on SolidRun Clearfog.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/ethernet/marvell/mvneta.c | 57 ++++++++++++++++++++++++++++++++---
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 61b23497f836..86bdb0eb463a 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -27,6 +27,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
+#include <linux/phy/phy.h>
 #include <linux/phy.h>
 #include <linux/phylink.h>
 #include <linux/platform_device.h>
@@ -436,6 +437,7 @@ struct mvneta_port {
 	struct device_node *dn;
 	unsigned int tx_csum_limit;
 	struct phylink *phylink;
+	struct phy *comphy;
 
 	struct mvneta_bm *bm_priv;
 	struct mvneta_bm_pool *pool_long;
@@ -3151,6 +3153,8 @@ static void mvneta_start_dev(struct mvneta_port *pp)
 {
 	int cpu;
 
+	WARN_ON(phy_power_on(pp->comphy));
+
 	mvneta_max_rx_size_set(pp, pp->pkt_size);
 	mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
 
@@ -3213,6 +3217,8 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
 
 	mvneta_tx_reset(pp);
 	mvneta_rx_reset(pp);
+
+	WARN_ON(phy_power_off(pp->comphy));
 }
 
 static void mvneta_percpu_enable(void *arg)
@@ -3338,6 +3344,7 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
 static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
 			    struct phylink_link_state *state)
 {
+	struct mvneta_port *pp = netdev_priv(ndev);
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 
 	/* We only support QSGMII, SGMII, 802.3z and RGMII modes */
@@ -3358,8 +3365,13 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
 	phylink_set(mask, Pause);
 
 	/* Half-duplex at speeds higher than 100Mbit is unsupported */
-	phylink_set(mask, 1000baseT_Full);
-	phylink_set(mask, 1000baseX_Full);
+	if (pp->comphy || state->interface != PHY_INTERFACE_MODE_2500BASEX) {
+		phylink_set(mask, 1000baseT_Full);
+		phylink_set(mask, 1000baseX_Full);
+	}
+	if (pp->comphy || state->interface == PHY_INTERFACE_MODE_2500BASEX) {
+		phylink_set(mask, 2500baseX_Full);
+	}
 
 	if (!phy_interface_mode_is_8023z(state->interface)) {
 		/* 10M and 100M are only supported in non-802.3z mode */
@@ -3373,6 +3385,11 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
 		   __ETHTOOL_LINK_MODE_MASK_NBITS);
 	bitmap_and(state->advertising, state->advertising, mask,
 		   __ETHTOOL_LINK_MODE_MASK_NBITS);
+
+	/* We can only operate at 2500BaseX or 1000BaseX.  If requested
+	 * to advertise both, only report advertising at 2500BaseX.
+	 */
+	phylink_helper_basex_speed(state);
 }
 
 static int mvneta_mac_link_state(struct net_device *ndev,
@@ -3384,7 +3401,9 @@ static int mvneta_mac_link_state(struct net_device *ndev,
 	gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
 
 	if (gmac_stat & MVNETA_GMAC_SPEED_1000)
-		state->speed = SPEED_1000;
+		state->speed =
+			state->interface == PHY_INTERFACE_MODE_2500BASEX ?
+			SPEED_2500 : SPEED_1000;
 	else if (gmac_stat & MVNETA_GMAC_SPEED_100)
 		state->speed = SPEED_100;
 	else
@@ -3499,12 +3518,32 @@ static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
 			    MVNETA_GMAC_FORCE_LINK_DOWN);
 	}
 
+
 	/* When at 2.5G, the link partner can send frames with shortened
 	 * preambles.
 	 */
 	if (state->speed == SPEED_2500)
 		new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE;
 
+	if (pp->comphy) {
+		enum phy_mode mode = PHY_MODE_INVALID;
+
+		switch (state->interface) {
+		case PHY_INTERFACE_MODE_SGMII:
+		case PHY_INTERFACE_MODE_1000BASEX:
+			mode = PHY_MODE_SGMII;
+			break;
+		case PHY_INTERFACE_MODE_2500BASEX:
+			mode = PHY_MODE_2500SGMII;
+			break;
+		default:
+			break;
+		}
+
+		if (mode != PHY_MODE_INVALID)
+			WARN_ON(phy_set_mode(pp->comphy, mode));
+	}
+
 	if (new_ctrl0 != gmac_ctrl0)
 		mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0);
 	if (new_ctrl2 != gmac_ctrl2)
@@ -4405,7 +4444,7 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 	if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
 		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
 	else if (phy_mode == PHY_INTERFACE_MODE_SGMII ||
-		 phy_mode == PHY_INTERFACE_MODE_1000BASEX)
+		 phy_interface_mode_is_8023z(phy_mode))
 		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
 	else if (!phy_interface_mode_is_rgmii(phy_mode))
 		return -EINVAL;
@@ -4422,6 +4461,7 @@ static int mvneta_probe(struct platform_device *pdev)
 	struct mvneta_port *pp;
 	struct net_device *dev;
 	struct phylink *phylink;
+	struct phy *comphy;
 	const char *dt_mac_addr;
 	char hw_mac_addr[ETH_ALEN];
 	const char *mac_from;
@@ -4447,6 +4487,14 @@ static int mvneta_probe(struct platform_device *pdev)
 		goto err_free_irq;
 	}
 
+	comphy = devm_of_phy_get(&pdev->dev, dn, NULL);
+	if (comphy == ERR_PTR(-EPROBE_DEFER)) {
+		err = -EPROBE_DEFER;
+		goto err_free_irq;
+	} else if (IS_ERR(comphy)) {
+		comphy = NULL;
+	}
+
 	phylink = phylink_create(dev, pdev->dev.fwnode, phy_mode,
 				 &mvneta_phylink_ops);
 	if (IS_ERR(phylink)) {
@@ -4463,6 +4511,7 @@ static int mvneta_probe(struct platform_device *pdev)
 	pp = netdev_priv(dev);
 	spin_lock_init(&pp->lock);
 	pp->phylink = phylink;
+	pp->comphy = comphy;
 	pp->phy_interface = phy_mode;
 	pp->dn = dn;
 
-- 
2.7.4


^ permalink raw reply related


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