netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ethtool: Add support for Wake-on-LAN using filters
  2018-08-06 21:29 [PATCH net-next " Florian Fainelli
@ 2018-08-06 21:29 ` Florian Fainelli
  0 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2018-08-06 21:29 UTC (permalink / raw)
  To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, linville, davem

Define a way to specify that a flow's action is to be used for
Wake-on-LAN purposes (using -2 as an action value) and define a new
Wake-on-LAN flag: 'f' which enables the Ethernet adapter for Wake-on-LAN
using filters.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 ethtool-copy.h | 2 ++
 ethtool.8.in   | 4 +++-
 ethtool.c      | 7 ++++++-
 rxclass.c      | 8 +++++---
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index 8cc61e9ab40b..943af3882aa1 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -1628,6 +1628,7 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
 #define WAKE_ARP		(1 << 4)
 #define WAKE_MAGIC		(1 << 5)
 #define WAKE_MAGICSECURE	(1 << 6) /* only meaningful if WAKE_MAGIC */
+#define WAKE_FILTER		(1 << 7)
 
 /* L2-L4 network traffic flow types */
 #define	TCP_V4_FLOW	0x01	/* hash or spec (tcp_ip4_spec) */
@@ -1665,6 +1666,7 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
 #define	RXH_DISCARD	(1 << 31)
 
 #define	RX_CLS_FLOW_DISC	0xffffffffffffffffULL
+#define RX_CLS_FLOW_WAKE	0xfffffffffffffffeULL
 
 /* Special RX classification rule insert location values */
 #define RX_CLS_LOC_SPECIAL	0x80000000	/* flag */
diff --git a/ethtool.8.in b/ethtool.8.in
index 0a366aa536ae..61923eed7c27 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -58,7 +58,7 @@
 .\"
 .\"	\(*WO - wol flags
 .\"
-.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBd\fP...
+.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBd|\fBf\fP...
 .\"
 .\"	\(*FL - flow type values
 .\"
@@ -679,6 +679,7 @@ b	Wake on broadcast messages
 a	Wake on ARP
 g	Wake on MagicPacket\[tm]
 s	Enable SecureOn\[tm] password for MagicPacket\[tm]
+f	Wake on filter(s)
 d	T{
 Disable (wake on nothing).  This option clears all previous options.
 T}
@@ -870,6 +871,7 @@ Specifies the Rx queue to send packets to, or some other action.
 nokeep;
 lB	l.
 -1	Drop the matched flow
+-2	Use the matched flow as a Wake-on-LAN filter
 0 or higher	Rx queue to route the flow
 .TE
 .TP
diff --git a/ethtool.c b/ethtool.c
index fb93ae898312..5e91ef9cecdb 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -931,6 +931,9 @@ static int parse_wolopts(char *optstr, u32 *data)
 		case 's':
 			*data |= WAKE_MAGICSECURE;
 			break;
+		case 'f':
+			*data |= WAKE_FILTER;
+			break;
 		case 'd':
 			*data = 0;
 			break;
@@ -964,6 +967,8 @@ static char *unparse_wolopts(int wolopts)
 			*p++ = 'g';
 		if (wolopts & WAKE_MAGICSECURE)
 			*p++ = 's';
+		if (wolopts & WAKE_FILTER)
+			*p++ = 'f';
 	} else {
 		*p = 'd';
 	}
@@ -4224,7 +4229,7 @@ static int flow_spec_to_ntuple(struct ethtool_rx_flow_spec *fsp,
 		return -1;
 
 	/* verify ring cookie can transfer to action */
-	if (fsp->ring_cookie > INT_MAX && fsp->ring_cookie < (u64)(-2))
+	if (fsp->ring_cookie > INT_MAX && fsp->ring_cookie < (u64)(-3))
 		return -1;
 
 	/* verify only one field is setting data field */
diff --git a/rxclass.c b/rxclass.c
index 42d122d1ed86..79972651e706 100644
--- a/rxclass.c
+++ b/rxclass.c
@@ -251,7 +251,11 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
 	if (fsp->flow_type & FLOW_RSS)
 		fprintf(stdout, "\tRSS Context ID: %u\n", rss_context);
 
-	if (fsp->ring_cookie != RX_CLS_FLOW_DISC) {
+	if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {
+		fprintf(stdout, "\tAction: Drop\n");
+	} else if (fsp->ring_cookie == RX_CLS_FLOW_WAKE) {
+		fprintf(stdout, "\tAction: Wake-on-LAN\n");
+	} else {
 		u64 vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
 		u64 queue = ethtool_get_flow_spec_ring(fsp->ring_cookie);
 
@@ -266,8 +270,6 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
 		else
 			fprintf(stdout, "\tAction: Direct to queue %llu\n",
 				queue);
-	} else {
-		fprintf(stdout, "\tAction: Drop\n");
 	}
 
 	fprintf(stdout, "\n");
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters
@ 2018-08-07 17:50 Florian Fainelli
  2018-08-07 17:50 ` [PATCH net-next v2 1/3] ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE Florian Fainelli
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Florian Fainelli @ 2018-08-07 17:50 UTC (permalink / raw)
  To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem, linville

Hi David, John,

This is technically a v2, but this patch series builds on your feedback
and defines the following:

- a new WAKE_* bit: WAKE_FILTER which can be enabled alongside other type
  of Wake-on-LAN to support waking up on a programmed filter (match + action)
- a new RX_CLS_FLOW_WAKE flow action which can be specified by an user when
  inserting a flow using ethtool::rxnfc, similar to the existing RX_CLS_FLOW_DISC

The bcm_sf2 and bcmsysport drivers are updated accordingly to work in concert to
allow matching packets at the switch level, identified by their filter location
to be used as a match by the SYSTEM PORT (CPU/management controller) during
Wake-on-LAN.

Let me know if this looks better than the previous incarnation of the patch
series.

Attached is also the ethtool patch that I would be submitting once the uapi
changes are committed.

Thank you!

Changes in v2:

- bail out earlier in bcm_sf2_cfp's get_rxnfc if an error is
  encountered (Andrew)

Florian Fainelli (3):
  ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE
  net: dsa: bcm_sf2: Propagate ethtool::rxnfc to CPU port
  net: systemport: Add support for WAKE_FILTER

 drivers/net/dsa/bcm_sf2_cfp.c              |  43 ++++-
 drivers/net/ethernet/broadcom/bcmsysport.c | 193 ++++++++++++++++++++-
 drivers/net/ethernet/broadcom/bcmsysport.h |  11 +-
 include/uapi/linux/ethtool.h               |   5 +-
 4 files changed, 239 insertions(+), 13 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net-next v2 1/3] ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE
  2018-08-07 17:50 [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters Florian Fainelli
@ 2018-08-07 17:50 ` Florian Fainelli
  2018-08-07 17:50 ` [PATCH] ethtool: Add support for Wake-on-LAN using filters Florian Fainelli
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2018-08-07 17:50 UTC (permalink / raw)
  To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem, linville

Add the ability to specify through ethtool::rxnfc that a rule location is
special and will be used to participate in Wake-on-LAN, by e.g: having a
specific pattern be matched. When this is the case, fs->ring_cookie must
be set to the special value RX_CLS_FLOW_WAKE.

We also define an additional ethtool::wolinfo flag: WAKE_FILTER which
can be used to configure an Ethernet adapter to allow Wake-on-LAN using
previously programmed filters.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/uapi/linux/ethtool.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 813282cc8af6..dc69391d2bba 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -870,7 +870,8 @@ struct ethtool_flow_ext {
  *	includes the %FLOW_EXT or %FLOW_MAC_EXT flag
  *	(see &struct ethtool_flow_ext description).
  * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
- *	if packets should be discarded
+ *	if packets should be discarded, or %RX_CLS_FLOW_WAKE if the
+ *	packets should be used for Wake-on-LAN with %WAKE_FILTER
  * @location: Location of rule in the table.  Locations must be
  *	numbered such that a flow matching multiple rules will be
  *	classified according to the first (lowest numbered) rule.
@@ -1634,6 +1635,7 @@ static inline int ethtool_validate_duplex(__u8 duplex)
 #define WAKE_ARP		(1 << 4)
 #define WAKE_MAGIC		(1 << 5)
 #define WAKE_MAGICSECURE	(1 << 6) /* only meaningful if WAKE_MAGIC */
+#define WAKE_FILTER		(1 << 7)
 
 /* L2-L4 network traffic flow types */
 #define	TCP_V4_FLOW	0x01	/* hash or spec (tcp_ip4_spec) */
@@ -1671,6 +1673,7 @@ static inline int ethtool_validate_duplex(__u8 duplex)
 #define	RXH_DISCARD	(1 << 31)
 
 #define	RX_CLS_FLOW_DISC	0xffffffffffffffffULL
+#define RX_CLS_FLOW_WAKE	0xfffffffffffffffeULL
 
 /* Special RX classification rule insert location values */
 #define RX_CLS_LOC_SPECIAL	0x80000000	/* flag */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH] ethtool: Add support for Wake-on-LAN using filters
  2018-08-07 17:50 [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters Florian Fainelli
  2018-08-07 17:50 ` [PATCH net-next v2 1/3] ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE Florian Fainelli
@ 2018-08-07 17:50 ` Florian Fainelli
  2018-08-07 17:50 ` [PATCH net-next v2 2/3] net: dsa: bcm_sf2: Propagate ethtool::rxnfc to CPU port Florian Fainelli
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2018-08-07 17:50 UTC (permalink / raw)
  To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem, linville

Define a way to specify that a flow's action is to be used for
Wake-on-LAN purposes (using -2 as an action value) and define a new
Wake-on-LAN flag: 'f' which enables the Ethernet adapter for Wake-on-LAN
using filters.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 ethtool-copy.h | 2 ++
 ethtool.8.in   | 4 +++-
 ethtool.c      | 7 ++++++-
 rxclass.c      | 8 +++++---
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index 8cc61e9ab40b..943af3882aa1 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -1628,6 +1628,7 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
 #define WAKE_ARP		(1 << 4)
 #define WAKE_MAGIC		(1 << 5)
 #define WAKE_MAGICSECURE	(1 << 6) /* only meaningful if WAKE_MAGIC */
+#define WAKE_FILTER		(1 << 7)
 
 /* L2-L4 network traffic flow types */
 #define	TCP_V4_FLOW	0x01	/* hash or spec (tcp_ip4_spec) */
@@ -1665,6 +1666,7 @@ static __inline__ int ethtool_validate_duplex(__u8 duplex)
 #define	RXH_DISCARD	(1 << 31)
 
 #define	RX_CLS_FLOW_DISC	0xffffffffffffffffULL
+#define RX_CLS_FLOW_WAKE	0xfffffffffffffffeULL
 
 /* Special RX classification rule insert location values */
 #define RX_CLS_LOC_SPECIAL	0x80000000	/* flag */
diff --git a/ethtool.8.in b/ethtool.8.in
index 0a366aa536ae..61923eed7c27 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -58,7 +58,7 @@
 .\"
 .\"	\(*WO - wol flags
 .\"
-.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBd\fP...
+.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBd|\fBf\fP...
 .\"
 .\"	\(*FL - flow type values
 .\"
@@ -679,6 +679,7 @@ b	Wake on broadcast messages
 a	Wake on ARP
 g	Wake on MagicPacket\[tm]
 s	Enable SecureOn\[tm] password for MagicPacket\[tm]
+f	Wake on filter(s)
 d	T{
 Disable (wake on nothing).  This option clears all previous options.
 T}
@@ -870,6 +871,7 @@ Specifies the Rx queue to send packets to, or some other action.
 nokeep;
 lB	l.
 -1	Drop the matched flow
+-2	Use the matched flow as a Wake-on-LAN filter
 0 or higher	Rx queue to route the flow
 .TE
 .TP
diff --git a/ethtool.c b/ethtool.c
index fb93ae898312..5e91ef9cecdb 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -931,6 +931,9 @@ static int parse_wolopts(char *optstr, u32 *data)
 		case 's':
 			*data |= WAKE_MAGICSECURE;
 			break;
+		case 'f':
+			*data |= WAKE_FILTER;
+			break;
 		case 'd':
 			*data = 0;
 			break;
@@ -964,6 +967,8 @@ static char *unparse_wolopts(int wolopts)
 			*p++ = 'g';
 		if (wolopts & WAKE_MAGICSECURE)
 			*p++ = 's';
+		if (wolopts & WAKE_FILTER)
+			*p++ = 'f';
 	} else {
 		*p = 'd';
 	}
@@ -4224,7 +4229,7 @@ static int flow_spec_to_ntuple(struct ethtool_rx_flow_spec *fsp,
 		return -1;
 
 	/* verify ring cookie can transfer to action */
-	if (fsp->ring_cookie > INT_MAX && fsp->ring_cookie < (u64)(-2))
+	if (fsp->ring_cookie > INT_MAX && fsp->ring_cookie < (u64)(-3))
 		return -1;
 
 	/* verify only one field is setting data field */
diff --git a/rxclass.c b/rxclass.c
index 42d122d1ed86..79972651e706 100644
--- a/rxclass.c
+++ b/rxclass.c
@@ -251,7 +251,11 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
 	if (fsp->flow_type & FLOW_RSS)
 		fprintf(stdout, "\tRSS Context ID: %u\n", rss_context);
 
-	if (fsp->ring_cookie != RX_CLS_FLOW_DISC) {
+	if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {
+		fprintf(stdout, "\tAction: Drop\n");
+	} else if (fsp->ring_cookie == RX_CLS_FLOW_WAKE) {
+		fprintf(stdout, "\tAction: Wake-on-LAN\n");
+	} else {
 		u64 vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
 		u64 queue = ethtool_get_flow_spec_ring(fsp->ring_cookie);
 
@@ -266,8 +270,6 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp,
 		else
 			fprintf(stdout, "\tAction: Direct to queue %llu\n",
 				queue);
-	} else {
-		fprintf(stdout, "\tAction: Drop\n");
 	}
 
 	fprintf(stdout, "\n");
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net-next v2 2/3] net: dsa: bcm_sf2: Propagate ethtool::rxnfc to CPU port
  2018-08-07 17:50 [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters Florian Fainelli
  2018-08-07 17:50 ` [PATCH net-next v2 1/3] ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE Florian Fainelli
  2018-08-07 17:50 ` [PATCH] ethtool: Add support for Wake-on-LAN using filters Florian Fainelli
@ 2018-08-07 17:50 ` Florian Fainelli
  2018-08-07 17:50 ` [PATCH net-next v2 3/3] net: systemport: Add support for WAKE_FILTER Florian Fainelli
  2018-08-07 19:15 ` [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters David Miller
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2018-08-07 17:50 UTC (permalink / raw)
  To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem, linville

Allow propagating ethtool::rxnfc programming to the CPU/management port
such that it is possible for such a CPU to perform e.g: Wake-on-LAN
using filters configured by the switch. We need a tiny bit of
cooperation between the switch drivers which is able to do the full flow
matching, whereas the CPU/management port might not. The CPU/management
driver needs to return -EOPNOTSUPP to indicate an non critical error,
any other error code otherwise.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/bcm_sf2_cfp.c | 43 ++++++++++++++++++++++++++++++++---
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index 1e37b65aab93..47c5f272a084 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -732,6 +732,8 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
 				struct ethtool_rx_flow_spec *fs)
 {
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+	s8 cpu_port = ds->ports[port].cpu_dp->index;
+	__u64 ring_cookie = fs->ring_cookie;
 	unsigned int queue_num, port_num;
 	int ret = -EINVAL;
 
@@ -748,13 +750,19 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
 	    fs->location > bcm_sf2_cfp_rule_size(priv))
 		return -EINVAL;
 
+	/* This rule is a Wake-on-LAN filter and we must specifically
+	 * target the CPU port in order for it to be working.
+	 */
+	if (ring_cookie == RX_CLS_FLOW_WAKE)
+		ring_cookie = cpu_port * SF2_NUM_EGRESS_QUEUES;
+
 	/* We do not support discarding packets, check that the
 	 * destination port is enabled and that we are within the
 	 * number of ports supported by the switch
 	 */
-	port_num = fs->ring_cookie / SF2_NUM_EGRESS_QUEUES;
+	port_num = ring_cookie / SF2_NUM_EGRESS_QUEUES;
 
-	if (fs->ring_cookie == RX_CLS_FLOW_DISC ||
+	if (ring_cookie == RX_CLS_FLOW_DISC ||
 	    !(dsa_is_user_port(ds, port_num) ||
 	      dsa_is_cpu_port(ds, port_num)) ||
 	    port_num >= priv->hw_params.num_ports)
@@ -763,7 +771,7 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
 	 * We have a small oddity where Port 6 just does not have a
 	 * valid bit here (so we substract by one).
 	 */
-	queue_num = fs->ring_cookie % SF2_NUM_EGRESS_QUEUES;
+	queue_num = ring_cookie % SF2_NUM_EGRESS_QUEUES;
 	if (port_num >= 7)
 		port_num -= 1;
 
@@ -1188,6 +1196,7 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
 int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
 		      struct ethtool_rxnfc *nfc, u32 *rule_locs)
 {
+	struct net_device *p = ds->ports[port].cpu_dp->master;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	int ret = 0;
 
@@ -1214,12 +1223,23 @@ int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
 
 	mutex_unlock(&priv->cfp.lock);
 
+	if (ret)
+		return ret;
+
+	/* Pass up the commands to the attached master network device */
+	if (p->ethtool_ops->get_rxnfc) {
+		ret = p->ethtool_ops->get_rxnfc(p, nfc, rule_locs);
+		if (ret == -EOPNOTSUPP)
+			ret = 0;
+	}
+
 	return ret;
 }
 
 int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
 		      struct ethtool_rxnfc *nfc)
 {
+	struct net_device *p = ds->ports[port].cpu_dp->master;
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	int ret = 0;
 
@@ -1240,6 +1260,23 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
 
 	mutex_unlock(&priv->cfp.lock);
 
+	if (ret)
+		return ret;
+
+	/* Pass up the commands to the attached master network device.
+	 * This can fail, so rollback the operation if we need to.
+	 */
+	if (p->ethtool_ops->set_rxnfc) {
+		ret = p->ethtool_ops->set_rxnfc(p, nfc);
+		if (ret && ret != -EOPNOTSUPP) {
+			mutex_lock(&priv->cfp.lock);
+			bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
+			mutex_unlock(&priv->cfp.lock);
+		} else {
+			ret = 0;
+		}
+	}
+
 	return ret;
 }
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net-next v2 3/3] net: systemport: Add support for WAKE_FILTER
  2018-08-07 17:50 [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters Florian Fainelli
                   ` (2 preceding siblings ...)
  2018-08-07 17:50 ` [PATCH net-next v2 2/3] net: dsa: bcm_sf2: Propagate ethtool::rxnfc to CPU port Florian Fainelli
@ 2018-08-07 17:50 ` Florian Fainelli
  2018-08-07 19:15 ` [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters David Miller
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Fainelli @ 2018-08-07 17:50 UTC (permalink / raw)
  To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem, linville

The SYSTEMPORT MAC allows up to 8 filters to be programmed to wake-up
from LAN. Verify that we have up to 8 filters and program them to the
appropriate RXCHK entries to be matched (along with their masks).

We need to update the entry and exit to Wake-on-LAN mode to keep the
RXCHK engine running to match during suspend, but this is otherwise
fairly similar to Magic Packet detection.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/bcmsysport.c | 193 ++++++++++++++++++++-
 drivers/net/ethernet/broadcom/bcmsysport.h |  11 +-
 2 files changed, 195 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 284581c9680e..ca47309d4494 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -521,7 +521,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	u32 reg;
 
-	wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+	wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
 	wol->wolopts = priv->wolopts;
 
 	if (!(priv->wolopts & WAKE_MAGICSECURE))
@@ -539,7 +539,7 @@ static int bcm_sysport_set_wol(struct net_device *dev,
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	struct device *kdev = &priv->pdev->dev;
-	u32 supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+	u32 supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
 
 	if (!device_can_wakeup(kdev))
 		return -ENOTSUPP;
@@ -1043,7 +1043,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
 
 static void mpd_enable_set(struct bcm_sysport_priv *priv, bool enable)
 {
-	u32 reg;
+	u32 reg, bit;
 
 	reg = umac_readl(priv, UMAC_MPD_CTRL);
 	if (enable)
@@ -1051,12 +1051,32 @@ static void mpd_enable_set(struct bcm_sysport_priv *priv, bool enable)
 	else
 		reg &= ~MPD_EN;
 	umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+	if (priv->is_lite)
+		bit = RBUF_ACPI_EN_LITE;
+	else
+		bit = RBUF_ACPI_EN;
+
+	reg = rbuf_readl(priv, RBUF_CONTROL);
+	if (enable)
+		reg |= bit;
+	else
+		reg &= ~bit;
+	rbuf_writel(priv, reg, RBUF_CONTROL);
 }
 
 static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
 {
+	u32 reg;
+
 	/* Stop monitoring MPD interrupt */
-	intrl2_0_mask_set(priv, INTRL2_0_MPD);
+	intrl2_0_mask_set(priv, INTRL2_0_MPD | INTRL2_0_BRCM_MATCH_TAG);
+
+	/* Disable RXCHK, active filters and Broadcom tag matching */
+	reg = rxchk_readl(priv, RXCHK_CONTROL);
+	reg &= ~(RXCHK_BRCM_TAG_MATCH_MASK <<
+		 RXCHK_BRCM_TAG_MATCH_SHIFT | RXCHK_EN | RXCHK_BRCM_TAG_EN);
+	rxchk_writel(priv, reg, RXCHK_CONTROL);
 
 	/* Clear the MagicPacket detection logic */
 	mpd_enable_set(priv, false);
@@ -1085,6 +1105,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	struct bcm_sysport_tx_ring *txr;
 	unsigned int ring, ring_bit;
+	u32 reg;
 
 	priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) &
 			  ~intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
@@ -1111,7 +1132,14 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
 		bcm_sysport_tx_reclaim_all(priv);
 
 	if (priv->irq0_stat & INTRL2_0_MPD)
-		netdev_info(priv->netdev, "Wake-on-LAN interrupt!\n");
+		netdev_info(priv->netdev, "Wake-on-LAN (MPD) interrupt!\n");
+
+	if (priv->irq0_stat & INTRL2_0_BRCM_MATCH_TAG) {
+		reg = rxchk_readl(priv, RXCHK_BRCM_TAG_MATCH_STATUS) &
+				  RXCHK_BRCM_TAG_MATCH_MASK;
+		netdev_info(priv->netdev,
+			    "Wake-on-LAN (filters 0x%02x) interrupt!\n", reg);
+	}
 
 	if (!priv->is_lite)
 		goto out;
@@ -2096,6 +2124,132 @@ static int bcm_sysport_stop(struct net_device *dev)
 	return 0;
 }
 
+static int bcm_sysport_rule_find(struct bcm_sysport_priv *priv,
+				 u64 location)
+{
+	unsigned int index;
+	u32 reg;
+
+	for_each_set_bit(index, priv->filters, RXCHK_BRCM_TAG_MAX) {
+		reg = rxchk_readl(priv, RXCHK_BRCM_TAG(index));
+		reg >>= RXCHK_BRCM_TAG_CID_SHIFT;
+		reg &= RXCHK_BRCM_TAG_CID_MASK;
+		if (reg == location)
+			return index;
+	}
+
+	return -EINVAL;
+}
+
+static int bcm_sysport_rule_get(struct bcm_sysport_priv *priv,
+				struct ethtool_rxnfc *nfc)
+{
+	int index;
+
+	/* This is not a rule that we know about */
+	index = bcm_sysport_rule_find(priv, nfc->fs.location);
+	if (index < 0)
+		return -EOPNOTSUPP;
+
+	nfc->fs.ring_cookie = RX_CLS_FLOW_WAKE;
+
+	return 0;
+}
+
+static int bcm_sysport_rule_set(struct bcm_sysport_priv *priv,
+				struct ethtool_rxnfc *nfc)
+{
+	unsigned int index;
+	u32 reg;
+
+	/* We cannot match locations greater than what the classification ID
+	 * permits (256 entries)
+	 */
+	if (nfc->fs.location > RXCHK_BRCM_TAG_CID_MASK)
+		return -E2BIG;
+
+	/* We cannot support flows that are not destined for a wake-up */
+	if (nfc->fs.ring_cookie != RX_CLS_FLOW_WAKE)
+		return -EOPNOTSUPP;
+
+	/* All filters are already in use, we cannot match more rules */
+	if (bitmap_weight(priv->filters, RXCHK_BRCM_TAG_MAX) ==
+	    RXCHK_BRCM_TAG_MAX)
+		return -ENOSPC;
+
+	index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX);
+	if (index > RXCHK_BRCM_TAG_MAX)
+		return -ENOSPC;
+
+	/* Location is the classification ID, and index is the position
+	 * within one of our 8 possible filters to be programmed
+	 */
+	reg = rxchk_readl(priv, RXCHK_BRCM_TAG(index));
+	reg &= ~(RXCHK_BRCM_TAG_CID_MASK << RXCHK_BRCM_TAG_CID_SHIFT);
+	reg |= nfc->fs.location << RXCHK_BRCM_TAG_CID_SHIFT;
+	rxchk_writel(priv, reg, RXCHK_BRCM_TAG(index));
+	rxchk_writel(priv, 0xff00ffff, RXCHK_BRCM_TAG_MASK(index));
+
+	set_bit(index, priv->filters);
+
+	return 0;
+}
+
+static int bcm_sysport_rule_del(struct bcm_sysport_priv *priv,
+				u64 location)
+{
+	int index;
+
+	/* This is not a rule that we know about */
+	index = bcm_sysport_rule_find(priv, location);
+	if (index < 0)
+		return -EOPNOTSUPP;
+
+	/* No need to disable this filter if it was enabled, this will
+	 * be taken care of during suspend time by bcm_sysport_suspend_to_wol
+	 */
+	clear_bit(index, priv->filters);
+
+	return 0;
+}
+
+static int bcm_sysport_get_rxnfc(struct net_device *dev,
+				 struct ethtool_rxnfc *nfc, u32 *rule_locs)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	int ret = -EOPNOTSUPP;
+
+	switch (nfc->cmd) {
+	case ETHTOOL_GRXCLSRULE:
+		ret = bcm_sysport_rule_get(priv, nfc);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int bcm_sysport_set_rxnfc(struct net_device *dev,
+				 struct ethtool_rxnfc *nfc)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	int ret = -EOPNOTSUPP;
+
+	switch (nfc->cmd) {
+	case ETHTOOL_SRXCLSRLINS:
+		ret = bcm_sysport_rule_set(priv, nfc);
+		break;
+	case ETHTOOL_SRXCLSRLDEL:
+		ret = bcm_sysport_rule_del(priv, nfc->fs.location);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
 static const struct ethtool_ops bcm_sysport_ethtool_ops = {
 	.get_drvinfo		= bcm_sysport_get_drvinfo,
 	.get_msglevel		= bcm_sysport_get_msglvl,
@@ -2110,6 +2264,8 @@ static const struct ethtool_ops bcm_sysport_ethtool_ops = {
 	.set_coalesce		= bcm_sysport_set_coalesce,
 	.get_link_ksettings     = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings     = phy_ethtool_set_link_ksettings,
+	.get_rxnfc		= bcm_sysport_get_rxnfc,
+	.set_rxnfc		= bcm_sysport_set_rxnfc,
 };
 
 static u16 bcm_sysport_select_queue(struct net_device *dev, struct sk_buff *skb,
@@ -2434,16 +2590,39 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
 {
 	struct net_device *ndev = priv->netdev;
 	unsigned int timeout = 1000;
+	unsigned int index, i = 0;
 	u32 reg;
 
 	/* Password has already been programmed */
 	reg = umac_readl(priv, UMAC_MPD_CTRL);
-	reg |= MPD_EN;
+	if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE))
+		reg |= MPD_EN;
 	reg &= ~PSW_EN;
 	if (priv->wolopts & WAKE_MAGICSECURE)
 		reg |= PSW_EN;
 	umac_writel(priv, reg, UMAC_MPD_CTRL);
 
+	if (priv->wolopts & WAKE_FILTER) {
+		/* Turn on ACPI matching to steal packets from RBUF */
+		reg = rbuf_readl(priv, RBUF_CONTROL);
+		if (priv->is_lite)
+			reg |= RBUF_ACPI_EN_LITE;
+		else
+			reg |= RBUF_ACPI_EN;
+		rbuf_writel(priv, reg, RBUF_CONTROL);
+
+		/* Enable RXCHK, active filters and Broadcom tag matching */
+		reg = rxchk_readl(priv, RXCHK_CONTROL);
+		reg &= ~(RXCHK_BRCM_TAG_MATCH_MASK <<
+			 RXCHK_BRCM_TAG_MATCH_SHIFT);
+		for_each_set_bit(index, priv->filters, RXCHK_BRCM_TAG_MAX) {
+			reg |= BIT(RXCHK_BRCM_TAG_MATCH_SHIFT + i);
+			i++;
+		}
+		reg |= RXCHK_EN | RXCHK_BRCM_TAG_EN;
+		rxchk_writel(priv, reg, RXCHK_CONTROL);
+	}
+
 	/* Make sure RBUF entered WoL mode as result */
 	do {
 		reg = rbuf_readl(priv, RBUF_STATUS);
@@ -2464,7 +2643,7 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
 	umac_enable_set(priv, CMD_RX_EN, 1);
 
 	/* Enable the interrupt wake-up source */
-	intrl2_0_mask_clear(priv, INTRL2_0_MPD);
+	intrl2_0_mask_clear(priv, INTRL2_0_MPD | INTRL2_0_BRCM_MATCH_TAG);
 
 	netif_dbg(priv, wol, ndev, "entered WOL mode\n");
 
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index cf440b91fd04..046c6c1d97fd 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -11,6 +11,7 @@
 #ifndef __BCM_SYSPORT_H
 #define __BCM_SYSPORT_H
 
+#include <linux/bitmap.h>
 #include <linux/if_vlan.h>
 #include <linux/net_dim.h>
 
@@ -155,14 +156,18 @@ struct bcm_rsb {
 #define  RXCHK_PARSE_AUTH		(1 << 22)
 
 #define RXCHK_BRCM_TAG0			0x04
-#define RXCHK_BRCM_TAG(i)		((i) * RXCHK_BRCM_TAG0)
+#define RXCHK_BRCM_TAG(i)		((i) * 0x4 + RXCHK_BRCM_TAG0)
 #define RXCHK_BRCM_TAG0_MASK		0x24
-#define RXCHK_BRCM_TAG_MASK(i)		((i) * RXCHK_BRCM_TAG0_MASK)
+#define RXCHK_BRCM_TAG_MASK(i)		((i) * 0x4 + RXCHK_BRCM_TAG0_MASK)
 #define RXCHK_BRCM_TAG_MATCH_STATUS	0x44
 #define RXCHK_ETHERTYPE			0x48
 #define RXCHK_BAD_CSUM_CNTR		0x4C
 #define RXCHK_OTHER_DISC_CNTR		0x50
 
+#define RXCHK_BRCM_TAG_MAX		8
+#define RXCHK_BRCM_TAG_CID_SHIFT	16
+#define RXCHK_BRCM_TAG_CID_MASK		0xff
+
 /* TXCHCK offsets and defines */
 #define SYS_PORT_TXCHK_OFFSET		0x380
 #define TXCHK_PKT_RDY_THRESH		0x00
@@ -185,6 +190,7 @@ struct bcm_rsb {
 #define  RBUF_RSB_SWAP0			(1 << 22)
 #define  RBUF_RSB_SWAP1			(1 << 23)
 #define  RBUF_ACPI_EN			(1 << 23)
+#define  RBUF_ACPI_EN_LITE		(1 << 24)
 
 #define RBUF_PKT_RDY_THRESH		0x04
 
@@ -777,6 +783,7 @@ struct bcm_sysport_priv {
 
 	/* Ethtool */
 	u32			msg_enable;
+	DECLARE_BITMAP(filters, RXCHK_BRCM_TAG_MAX);
 
 	struct bcm_sysport_stats64	stats64;
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters
  2018-08-07 17:50 [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters Florian Fainelli
                   ` (3 preceding siblings ...)
  2018-08-07 17:50 ` [PATCH net-next v2 3/3] net: systemport: Add support for WAKE_FILTER Florian Fainelli
@ 2018-08-07 19:15 ` David Miller
  4 siblings, 0 replies; 7+ messages in thread
From: David Miller @ 2018-08-07 19:15 UTC (permalink / raw)
  To: f.fainelli; +Cc: netdev, andrew, vivien.didelot, linville

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Tue,  7 Aug 2018 10:50:19 -0700

> This is technically a v2, but this patch series builds on your feedback
> and defines the following:
> 
> - a new WAKE_* bit: WAKE_FILTER which can be enabled alongside other type
>   of Wake-on-LAN to support waking up on a programmed filter (match + action)
> - a new RX_CLS_FLOW_WAKE flow action which can be specified by an user when
>   inserting a flow using ethtool::rxnfc, similar to the existing RX_CLS_FLOW_DISC
> 
> The bcm_sf2 and bcmsysport drivers are updated accordingly to work in concert to
> allow matching packets at the switch level, identified by their filter location
> to be used as a match by the SYSTEM PORT (CPU/management controller) during
> Wake-on-LAN.
> 
> Let me know if this looks better than the previous incarnation of the patch
> series.

This looks a lot better.

Series applied to net-next, thanks Florian.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-08-07 21:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-07 17:50 [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters Florian Fainelli
2018-08-07 17:50 ` [PATCH net-next v2 1/3] ethtool: Add WAKE_FILTER and RX_CLS_FLOW_WAKE Florian Fainelli
2018-08-07 17:50 ` [PATCH] ethtool: Add support for Wake-on-LAN using filters Florian Fainelli
2018-08-07 17:50 ` [PATCH net-next v2 2/3] net: dsa: bcm_sf2: Propagate ethtool::rxnfc to CPU port Florian Fainelli
2018-08-07 17:50 ` [PATCH net-next v2 3/3] net: systemport: Add support for WAKE_FILTER Florian Fainelli
2018-08-07 19:15 ` [PATCH net-next v2 0/3] net: Support Wake-on-LAN using filters David Miller
  -- strict thread matches above, loose matches on Subject: below --
2018-08-06 21:29 [PATCH net-next " Florian Fainelli
2018-08-06 21:29 ` [PATCH] ethtool: Add support for " Florian Fainelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).