Netdev List
 help / color / mirror / Atom feed
* [iproute PATCH] Use ARRAY_SIZE macro everywhere
From: Phil Sutter @ 2016-03-17 19:28 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

This patch was generated by the following semantic patch (a trimmed down
version of what is shipped with Linux sources):

@@
type T;
T[] E;
@@
(
- (sizeof(E)/sizeof(*E))
+ ARRAY_SIZE(E)
|
- (sizeof(E)/sizeof(E[...]))
+ ARRAY_SIZE(E)
|
- (sizeof(E)/sizeof(T))
+ ARRAY_SIZE(E)
)

The only manual adjustment was to include utils.h in misc/nstat.c to make
the macro known there.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 bridge/link.c          | 6 +++---
 ip/ipaddress.c         | 6 +++---
 ip/iplink_bond_slave.c | 4 ++--
 misc/nstat.c           | 3 ++-
 misc/ss.c              | 2 +-
 tc/em_meta.c           | 6 +++---
 tc/f_u32.c             | 2 +-
 7 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/bridge/link.c b/bridge/link.c
index a9b1262dfdc2d..7ecc67f34b349 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -69,7 +69,7 @@ static const char *hw_mode[] = {"VEB", "VEPA"};
 
 static void print_operstate(FILE *f, __u8 state)
 {
-	if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
+	if (state >= ARRAY_SIZE(oper_states))
 		fprintf(f, "state %#x ", state);
 	else
 		fprintf(f, "state %s ", oper_states[state]);
@@ -90,7 +90,7 @@ static void print_onoff(FILE *f, char *flag, __u8 val)
 
 static void print_hwmode(FILE *f, __u16 mode)
 {
-	if (mode >= sizeof(hw_mode)/sizeof(hw_mode[0]))
+	if (mode >= ARRAY_SIZE(hw_mode))
 		fprintf(f, "hwmode %#hx ", mode);
 	else
 		fprintf(f, "hwmode %s ", hw_mode[mode]);
@@ -318,7 +318,7 @@ static int brlink_modify(int argc, char **argv)
 		} else if (strcmp(*argv, "state") == 0) {
 			NEXT_ARG();
 			char *endptr;
-			size_t nstates = sizeof(port_states) / sizeof(*port_states);
+			size_t nstates = ARRAY_SIZE(port_states);
 			state = strtol(*argv, &endptr, 10);
 			if (!(**argv != '\0' && *endptr == '\0')) {
 				for (state = 0; state < nstates; state++)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 73505d1769b6c..6f967a0329b49 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -135,7 +135,7 @@ static const char *oper_states[] = {
 
 static void print_operstate(FILE *f, __u8 state)
 {
-	if (state >= sizeof(oper_states)/sizeof(oper_states[0])) {
+	if (state >= ARRAY_SIZE(oper_states)) {
 		fprintf(f, "state %#x ", state);
 	} else if (brief) {
 		color_fprintf(f, oper_state_color(state),
@@ -151,7 +151,7 @@ int get_operstate(const char *name)
 {
 	int i;
 
-	for (i = 0; i < sizeof(oper_states)/sizeof(oper_states[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(oper_states); i++)
 		if (strcasecmp(name, oper_states[i]) == 0)
 			return i;
 	return -1;
@@ -192,7 +192,7 @@ static void print_linkmode(FILE *f, struct rtattr *tb)
 {
 	unsigned int mode = rta_getattr_u8(tb);
 
-	if (mode >= sizeof(link_modes) / sizeof(link_modes[0]))
+	if (mode >= ARRAY_SIZE(link_modes))
 		fprintf(f, "mode %d ", mode);
 	else
 		fprintf(f, "mode %s ", link_modes[mode]);
diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c
index 2f3364ee45a54..d67793237edfc 100644
--- a/ip/iplink_bond_slave.c
+++ b/ip/iplink_bond_slave.c
@@ -26,7 +26,7 @@ static void print_slave_state(FILE *f, struct rtattr *tb)
 {
 	unsigned int state = rta_getattr_u8(tb);
 
-	if (state >= sizeof(slave_states) / sizeof(slave_states[0]))
+	if (state >= ARRAY_SIZE(slave_states))
 		fprintf(f, "state %d ", state);
 	else
 		fprintf(f, "state %s ", slave_states[state]);
@@ -43,7 +43,7 @@ static void print_slave_mii_status(FILE *f, struct rtattr *tb)
 {
 	unsigned int status = rta_getattr_u8(tb);
 
-	if (status >= sizeof(slave_mii_status) / sizeof(slave_mii_status[0]))
+	if (status >= ARRAY_SIZE(slave_mii_status))
 		fprintf(f, "mii_status %d ", status);
 	else
 		fprintf(f, "mii_status %s ", slave_mii_status[status]);
diff --git a/misc/nstat.c b/misc/nstat.c
index 22b27eba7c8f6..cc19b1cd89356 100644
--- a/misc/nstat.c
+++ b/misc/nstat.c
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <math.h>
 #include <getopt.h>
+#include <utils.h>
 
 #include <json_writer.h>
 #include <SNAPSHOT.h>
@@ -94,7 +95,7 @@ static const char *useless_numbers[] = {
 static int useless_number(const char *id)
 {
 	int i;
-	for (i=0; i<sizeof(useless_numbers)/sizeof(*useless_numbers); i++)
+	for (i=0; i<ARRAY_SIZE(useless_numbers); i++)
 		if (strcmp(id, useless_numbers[i]) == 0)
 			return 1;
 	return 0;
diff --git a/misc/ss.c b/misc/ss.c
index c1026a9de6997..24d1b28602a69 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -668,7 +668,7 @@ static int get_slabstat(struct slabstat *s)
 	}
 	while(fgets(buf, sizeof(buf), fp) != NULL) {
 		int i;
-		for (i=0; i<sizeof(slabstat_ids)/sizeof(slabstat_ids[0]); i++) {
+		for (i=0; i<ARRAY_SIZE(slabstat_ids); i++) {
 			if (memcmp(buf, slabstat_ids[i], strlen(slabstat_ids[i])) == 0) {
 				sscanf(buf, "%*s%d", ((int *)s) + i);
 				cnt--;
diff --git a/tc/em_meta.c b/tc/em_meta.c
index b64f333e5cb5b..bc871315d1d18 100644
--- a/tc/em_meta.c
+++ b/tc/em_meta.c
@@ -126,7 +126,7 @@ static struct meta_entry * lookup_meta_entry(struct bstr *kind)
 {
 	int i;
 
-	for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++)
+	for (i = 0; i < ARRAY_SIZE(meta_table); i++)
 		if (!bstrcmp(kind, meta_table[i].kind) &&
 		    meta_table[i].id != 0)
 			return &meta_table[i];
@@ -138,7 +138,7 @@ static struct meta_entry * lookup_meta_entry_byid(int id)
 {
 	int i;
 
-	for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++)
+	for (i = 0; i < ARRAY_SIZE(meta_table); i++)
 		if (meta_table[i].id == id)
 			return &meta_table[i];
 
@@ -192,7 +192,7 @@ static void list_meta_ids(FILE *fd)
 	    "  ID               Type       Description\n" \
 	    "--------------------------------------------------------");
 
-	for (i = 0; i < (sizeof(meta_table)/sizeof(meta_table[0])); i++) {
+	for (i = 0; i < ARRAY_SIZE(meta_table); i++) {
 		if (meta_table[i].id == TCF_META_ID_SECTION) {
 			fprintf(fd, "\n%s:\n", meta_table[i].kind);
 		} else {
diff --git a/tc/f_u32.c b/tc/f_u32.c
index 0b97678933a62..0fb671072b793 100644
--- a/tc/f_u32.c
+++ b/tc/f_u32.c
@@ -958,7 +958,7 @@ static void show_keys(FILE *f, const struct tc_u32_key *key)
 	if (!show_pretty)
 		goto show_k;
 
-	for (i = 0; i < sizeof(u32_pprinters) / sizeof(u32_pprinters[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(u32_pprinters); i++) {
 		if (u32_pprinters[i].proto == ntohs(f_proto)) {
 show_k:
 			u32_pprinters[i].pprinter(f, key);
-- 
2.7.2

^ permalink raw reply related

* [PATCH v2 ethtool 2/2] Documentation for IPv6 NFC
From: Edward Cree @ 2016-03-17 19:17 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev
In-Reply-To: <56EB00D6.3060003@solarflare.com>

Leaves 'src-ip' and 'dst-ip' documented as taking x.x.x.x, because there's
more low-level nroff here than I can parse, let alone emit.

Signed-off-by: Edward Cree <ecree@solarflare.com>
---
 ethtool.8.in | 29 ++++++++++++++++++++---------
 ethtool.c    |  4 +++-
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/ethtool.8.in b/ethtool.8.in
index 009711d..36da10e 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -74,7 +74,7 @@
 .\"
 .\"	\(*NC - Network Classifier type values
 .\"
-.ds NC \fBether\fP|\fBip4\fP|\fBtcp4\fP|\fBudp4\fP|\fBsctp4\fP|\fBah4\fP|\fBesp4\fP
+.ds NC \fBether\fP|\fBip4\fP|\fBtcp4\fP|\fBudp4\fP|\fBsctp4\fP|\fBah4\fP|\fBesp4\fP|\fBip6\fP|\fBtcp6\fP|\fBudp6\fP|\fBah6\fP|\fBesp6\fP|\fBsctp6\fP
 ..
 .\"
 .\" Start URL.
@@ -263,6 +263,7 @@ ethtool \- query or control network driver and hardware settings
 .RB [ src\-ip \ \*(PA\ [ m \ \*(PA]]
 .RB [ dst\-ip \ \*(PA\ [ m \ \*(PA]]
 .BM tos
+.BM tclass
 .BM l4proto
 .BM src\-port
 .BM dst\-port
@@ -710,6 +711,12 @@ udp4	UDP over IPv4
 sctp4	SCTP over IPv4
 ah4	IPSEC AH over IPv4
 esp4	IPSEC ESP over IPv4
+ip6	Raw IPv6
+tcp6	TCP over IPv6
+udp6	UDP over IPv6
+sctp6	SCTP over IPv6
+ah6	IPSEC AH over IPv6
+esp6	IPSEC ESP over IPv6
 .TE
 .PP
 For all fields that allow both a value and a mask to be specified, the
@@ -734,38 +741,42 @@ Valid only for flow-type ether.
 .TP
 .BR src\-ip \ \*(PA\ [ m \ \*(PA]
 Specify the source IP address of the incoming packet to match along with
-an optional mask.  Valid for all IPv4 based flow-types.
+an optional mask.  Valid for all IP based flow-types.
 .TP
 .BR dst\-ip \ \*(PA\ [ m \ \*(PA]
 Specify the destination IP address of the incoming packet to match along
-with an optional mask.  Valid for all IPv4 based flow-types.
+with an optional mask.  Valid for all IP based flow-types.
 .TP
 .BI tos \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Specify the value of the Type of Service field in the incoming packet to
 match along with an optional mask.  Applies to all IPv4 based flow-types.
 .TP
+.BI tclass \ N \\fR\ [\\fPm \ N \\fR]\\fP
+Specify the value of the Traffic Class field in the incoming packet to
+match along with an optional mask.  Applies to all IPv6 based flow-types.
+.TP
 .BI l4proto \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Includes the layer 4 protocol number and optional mask.  Valid only for
-flow-type ip4.
+flow-types ip4 and ip6.
 .TP
 .BI src\-port \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Specify the value of the source port field (applicable to TCP/UDP packets)
 in the incoming packet to match along with an optional mask.  Valid for
-flow-types ip4, tcp4, udp4, and sctp4.
+flow-types ip4, tcp4, udp4, and sctp4 and their IPv6 equivalents.
 .TP
 .BI dst\-port \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Specify the value of the destination port field (applicable to TCP/UDP
 packets)in the incoming packet to match along with an optional mask.
-Valid for flow-types ip4, tcp4, udp4, and sctp4.
+Valid for flow-types ip4, tcp4, udp4, and sctp4 and their IPv6 equivalents.
 .TP
 .BI spi \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Specify the value of the security parameter index field (applicable to
 AH/ESP packets)in the incoming packet to match along with an optional
-mask.  Valid for flow-types ip4, ah4, and esp4.
+mask.  Valid for flow-types ip4, ah4, and esp4 and their IPv6 equivalents.
 .TP
 .BI l4data \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Specify the value of the first 4 Bytes of Layer 4 in the incoming packet to
-match along with an optional mask.  Valid for ip4 flow-type.
+match along with an optional mask.  Valid for ip4 and ip6 flow-types.
 .TP
 .BI vlan\-etype \ N \\fR\ [\\fPm \ N \\fR]\\fP
 Includes the VLAN tag Ethertype and an optional mask.
@@ -779,7 +790,7 @@ Includes 64-bits of user-specific data and an optional mask.
 .BR dst-mac \ \*(MA\ [ m \ \*(MA]
 Includes the destination MAC address, specified as 6 bytes in hexadecimal
 separated by colons, along with an optional mask.
-Valid for all IPv4 based flow-types.
+Valid for all IP based flow-types.
 .TP
 .BI action \ N
 Specifies the Rx queue to send packets to, or some other action.
diff --git a/ethtool.c b/ethtool.c
index b476dcc..a92137f 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4158,13 +4158,15 @@ static const struct option {
 	  "Configure Rx network flow classification options or rules",
 	  "		rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|"
 	  "tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r... |\n"
-	  "		flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4\n"
+	  "		flow-type ether|ip4|tcp4|udp4|sctp4|ah4|esp4|"
+	  "ip6|tcp6|udp6|ah6|esp6|sctp6\n"
 	  "			[ src %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"
 	  "			[ dst %x:%x:%x:%x:%x:%x [m %x:%x:%x:%x:%x:%x] ]\n"
 	  "			[ proto %d [m %x] ]\n"
 	  "			[ src-ip %d.%d.%d.%d [m %d.%d.%d.%d] ]\n"
 	  "			[ dst-ip %d.%d.%d.%d [m %d.%d.%d.%d] ]\n"
 	  "			[ tos %d [m %x] ]\n"
+	  "			[ tclass %d [m %x] ]\n"
 	  "			[ l4proto %d [m %x] ]\n"
 	  "			[ src-port %d [m %x] ]\n"
 	  "			[ dst-port %d [m %x] ]\n"

^ permalink raw reply related

* [PATCH v2 ethtool 1/2] Add IPv6 support to NFC
From: Edward Cree @ 2016-03-17 19:17 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev
In-Reply-To: <56EB00D6.3060003@solarflare.com>

Signed-off-by: Edward Cree <ecree@solarflare.com>
---
 ethtool.c |  21 +++++
 rxclass.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 274 insertions(+), 14 deletions(-)

diff --git a/ethtool.c b/ethtool.c
index 0cd0d4f..b476dcc 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -32,6 +32,7 @@
 #include <sys/stat.h>
 #include <stdio.h>
 #include <stddef.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <sys/utsname.h>
 #include <limits.h>
@@ -3540,6 +3541,22 @@ static int do_permaddr(struct cmd_context *ctx)
 	return err;
 }
 
+static bool flow_type_is_ntuple_supported(__u32 flow_type)
+{
+	switch (flow_type) {
+	case TCP_V4_FLOW:
+	case UDP_V4_FLOW:
+	case SCTP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case IPV4_USER_FLOW:
+	case ETHER_FLOW:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static int flow_spec_to_ntuple(struct ethtool_rx_flow_spec *fsp,
 			       struct ethtool_rx_ntuple_flow_spec *ntuple)
 {
@@ -3563,6 +3580,10 @@ static int flow_spec_to_ntuple(struct ethtool_rx_flow_spec *fsp,
 	    fsp->m_ext.vlan_etype)
 		return -1;
 
+	/* IPv6 flow types are not supported by ntuple */
+	if (!flow_type_is_ntuple_supported(fsp->flow_type & ~FLOW_EXT))
+		return -1;
+
 	/* Set entire ntuple to ~0 to guarantee all masks are set */
 	memset(ntuple, ~0, sizeof(*ntuple));
 
diff --git a/rxclass.c b/rxclass.c
index cd686a3..c7bfeba 100644
--- a/rxclass.c
+++ b/rxclass.c
@@ -39,6 +39,25 @@ static void rxclass_print_ipv4_rule(__be32 sip, __be32 sipm, __be32 dip,
 		tos, tosm);
 }
 
+static void rxclass_print_ipv6_rule(__be32 *sip, __be32 *sipm, __be32 *dip,
+				    __be32 *dipm, u8 tclass, u8 tclassm)
+{
+	char sip_str[INET6_ADDRSTRLEN];
+	char sipm_str[INET6_ADDRSTRLEN];
+	char dip_str[INET6_ADDRSTRLEN];
+	char dipm_str[INET6_ADDRSTRLEN];
+
+	fprintf(stdout,
+		"\tSrc IP addr: %s mask: %s\n"
+		"\tDest IP addr: %s mask: %s\n"
+		"\tTraffic Class: 0x%x mask: 0x%x\n",
+		inet_ntop(AF_INET6, sip, sip_str, INET6_ADDRSTRLEN),
+		inet_ntop(AF_INET6, sipm, sipm_str, INET6_ADDRSTRLEN),
+		inet_ntop(AF_INET6, dip, dip_str, INET6_ADDRSTRLEN),
+		inet_ntop(AF_INET6, dipm, dipm_str, INET6_ADDRSTRLEN),
+		tclass, tclassm);
+}
+
 static void rxclass_print_nfc_spec_ext(struct ethtool_rx_flow_spec *fsp)
 {
 	if (fsp->flow_type & FLOW_EXT) {
@@ -127,7 +146,7 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp)
 			ntohl(fsp->h_u.esp_ip4_spec.spi),
 			ntohl(fsp->m_u.esp_ip4_spec.spi));
 		break;
-	case IP_USER_FLOW:
+	case IPV4_USER_FLOW:
 		fprintf(stdout, "\tRule Type: Raw IPv4\n");
 		rxclass_print_ipv4_rule(fsp->h_u.usr_ip4_spec.ip4src,
 				     fsp->m_u.usr_ip4_spec.ip4src,
@@ -143,6 +162,62 @@ static void rxclass_print_nfc_rule(struct ethtool_rx_flow_spec *fsp)
 			ntohl(fsp->h_u.usr_ip4_spec.l4_4_bytes),
 			ntohl(fsp->m_u.usr_ip4_spec.l4_4_bytes));
 		break;
+	case TCP_V6_FLOW:
+	case UDP_V6_FLOW:
+	case SCTP_V6_FLOW:
+		if (flow_type == TCP_V6_FLOW)
+			fprintf(stdout, "\tRule Type: TCP over IPv6\n");
+		else if (flow_type == UDP_V6_FLOW)
+			fprintf(stdout, "\tRule Type: UDP over IPv6\n");
+		else
+			fprintf(stdout, "\tRule Type: SCTP over IPv6\n");
+		rxclass_print_ipv6_rule(fsp->h_u.tcp_ip6_spec.ip6src,
+				     fsp->m_u.tcp_ip6_spec.ip6src,
+				     fsp->h_u.tcp_ip6_spec.ip6dst,
+				     fsp->m_u.tcp_ip6_spec.ip6dst,
+				     fsp->h_u.tcp_ip6_spec.tclass,
+				     fsp->m_u.tcp_ip6_spec.tclass);
+		fprintf(stdout,
+			"\tSrc port: %d mask: 0x%x\n"
+			"\tDest port: %d mask: 0x%x\n",
+			ntohs(fsp->h_u.tcp_ip6_spec.psrc),
+			ntohs(fsp->m_u.tcp_ip6_spec.psrc),
+			ntohs(fsp->h_u.tcp_ip6_spec.pdst),
+			ntohs(fsp->m_u.tcp_ip6_spec.pdst));
+		break;
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+		if (flow_type == AH_V6_FLOW)
+			fprintf(stdout, "\tRule Type: IPSEC AH over IPv6\n");
+		else
+			fprintf(stdout, "\tRule Type: IPSEC ESP over IPv6\n");
+		rxclass_print_ipv6_rule(fsp->h_u.ah_ip6_spec.ip6src,
+				     fsp->m_u.ah_ip6_spec.ip6src,
+				     fsp->h_u.ah_ip6_spec.ip6dst,
+				     fsp->m_u.ah_ip6_spec.ip6dst,
+				     fsp->h_u.ah_ip6_spec.tclass,
+				     fsp->m_u.ah_ip6_spec.tclass);
+		fprintf(stdout,
+			"\tSPI: %d mask: 0x%x\n",
+			ntohl(fsp->h_u.esp_ip6_spec.spi),
+			ntohl(fsp->m_u.esp_ip6_spec.spi));
+		break;
+	case IPV6_USER_FLOW:
+		fprintf(stdout, "\tRule Type: Raw IPv6\n");
+		rxclass_print_ipv6_rule(fsp->h_u.usr_ip6_spec.ip6src,
+				     fsp->m_u.usr_ip6_spec.ip6src,
+				     fsp->h_u.usr_ip6_spec.ip6dst,
+				     fsp->m_u.usr_ip6_spec.ip6dst,
+				     fsp->h_u.usr_ip6_spec.tclass,
+				     fsp->m_u.usr_ip6_spec.tclass);
+		fprintf(stdout,
+			"\tProtocol: %d mask: 0x%x\n"
+			"\tL4 bytes: 0x%x mask: 0x%x\n",
+			fsp->h_u.usr_ip6_spec.l4_proto,
+			fsp->m_u.usr_ip6_spec.l4_proto,
+			ntohl(fsp->h_u.usr_ip6_spec.l4_4_bytes),
+			ntohl(fsp->m_u.usr_ip6_spec.l4_4_bytes));
+		break;
 	case ETHER_FLOW:
 		dmac = fsp->h_u.ether_spec.h_dest;
 		dmacm = fsp->m_u.ether_spec.h_dest;
@@ -190,21 +265,20 @@ static void rxclass_print_rule(struct ethtool_rx_flow_spec *fsp)
 	case SCTP_V4_FLOW:
 	case AH_V4_FLOW:
 	case ESP_V4_FLOW:
-	case ETHER_FLOW:
-		rxclass_print_nfc_rule(fsp);
-		break;
-	case IP_USER_FLOW:
-		if (fsp->h_u.usr_ip4_spec.ip_ver == ETH_RX_NFC_IP4) {
-			rxclass_print_nfc_rule(fsp);
-			break;
-		}
-		/* IPv6 User Flow falls through to the case below */
 	case TCP_V6_FLOW:
 	case UDP_V6_FLOW:
 	case SCTP_V6_FLOW:
 	case AH_V6_FLOW:
 	case ESP_V6_FLOW:
-		fprintf(stderr, "IPv6 flows not implemented\n");
+	case IPV6_USER_FLOW:
+	case ETHER_FLOW:
+		rxclass_print_nfc_rule(fsp);
+		break;
+	case IPV4_USER_FLOW:
+		if (fsp->h_u.usr_ip4_spec.ip_ver == ETH_RX_NFC_IP4)
+			rxclass_print_nfc_rule(fsp);
+		else /* IPv6 uses IPV6_USER_FLOW */
+			fprintf(stderr, "IPV4_USER_FLOW with wrong ip_ver\n");
 		break;
 	default:
 		fprintf(stderr, "rxclass: Unknown flow type\n");
@@ -530,6 +604,7 @@ typedef enum {
 	OPT_BE32,
 	OPT_BE64,
 	OPT_IP4,
+	OPT_IP6,
 	OPT_MAC,
 } rule_opt_type_t;
 
@@ -663,6 +738,114 @@ static const struct rule_opts rule_nfc_usr_ip4[] = {
 	  offsetof(struct ethtool_rx_flow_spec, m_ext.h_dest) },
 };
 
+static const struct rule_opts rule_nfc_tcp_ip6[] = {
+	{ "src-ip", OPT_IP6, NFC_FLAG_SADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.ip6src),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip6_spec.ip6src) },
+	{ "dst-ip", OPT_IP6, NFC_FLAG_DADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.ip6dst),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip6_spec.ip6dst) },
+	{ "tclass", OPT_U8, NFC_FLAG_TOS,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.tclass),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip6_spec.tclass) },
+	{ "src-port", OPT_BE16, NFC_FLAG_SPORT,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.psrc),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip6_spec.psrc) },
+	{ "dst-port", OPT_BE16, NFC_FLAG_DPORT,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.pdst),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip6_spec.pdst) },
+	{ "action", OPT_U64, NFC_FLAG_RING,
+	  offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 },
+	{ "loc", OPT_U32, NFC_FLAG_LOC,
+	  offsetof(struct ethtool_rx_flow_spec, location), -1 },
+	{ "vlan-etype", OPT_BE16, NTUPLE_FLAG_VETH,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_etype),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_etype) },
+	{ "vlan", OPT_BE16, NTUPLE_FLAG_VLAN,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_tci),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_tci) },
+	{ "user-def", OPT_BE64, NTUPLE_FLAG_UDEF,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.data),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.data) },
+	{ "dst-mac", OPT_MAC, NFC_FLAG_MAC_ADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.h_dest),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.h_dest) },
+};
+
+static const struct rule_opts rule_nfc_esp_ip6[] = {
+	{ "src-ip", OPT_IP6, NFC_FLAG_SADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.esp_ip6_spec.ip6src),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.esp_ip6_spec.ip6src) },
+	{ "dst-ip", OPT_IP6, NFC_FLAG_DADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.esp_ip6_spec.ip6dst),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.esp_ip6_spec.ip6dst) },
+	{ "tclass", OPT_U8, NFC_FLAG_TOS,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.esp_ip6_spec.tclass),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.esp_ip6_spec.tclass) },
+	{ "spi", OPT_BE32, NFC_FLAG_SPI,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.esp_ip6_spec.spi),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.esp_ip6_spec.spi) },
+	{ "action", OPT_U64, NFC_FLAG_RING,
+	  offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 },
+	{ "loc", OPT_U32, NFC_FLAG_LOC,
+	  offsetof(struct ethtool_rx_flow_spec, location), -1 },
+	{ "vlan-etype", OPT_BE16, NTUPLE_FLAG_VETH,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_etype),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_etype) },
+	{ "vlan", OPT_BE16, NTUPLE_FLAG_VLAN,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_tci),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_tci) },
+	{ "user-def", OPT_BE64, NTUPLE_FLAG_UDEF,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.data),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.data) },
+	{ "dst-mac", OPT_MAC, NFC_FLAG_MAC_ADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.h_dest),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.h_dest) },
+};
+
+static const struct rule_opts rule_nfc_usr_ip6[] = {
+	{ "src-ip", OPT_IP6, NFC_FLAG_SADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.ip6src),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.ip6src) },
+	{ "dst-ip", OPT_IP6, NFC_FLAG_DADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.ip6dst),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.ip6dst) },
+	{ "tclass", OPT_U8, NFC_FLAG_TOS,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.tclass),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.tclass) },
+	{ "l4proto", OPT_U8, NFC_FLAG_PROTO,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.l4_proto),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.l4_proto) },
+	{ "l4data", OPT_BE32, NFC_FLAG_SPI,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.l4_4_bytes),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.l4_4_bytes) },
+	{ "spi", OPT_BE32, NFC_FLAG_SPI,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.l4_4_bytes),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.l4_4_bytes) },
+	{ "src-port", OPT_BE16, NFC_FLAG_SPORT,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.l4_4_bytes),
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.l4_4_bytes) },
+	{ "dst-port", OPT_BE16, NFC_FLAG_DPORT,
+	  offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.l4_4_bytes) + 2,
+	  offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.l4_4_bytes) + 2 },
+	{ "action", OPT_U64, NFC_FLAG_RING,
+	  offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 },
+	{ "loc", OPT_U32, NFC_FLAG_LOC,
+	  offsetof(struct ethtool_rx_flow_spec, location), -1 },
+	{ "vlan-etype", OPT_BE16, NTUPLE_FLAG_VETH,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_etype),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_etype) },
+	{ "vlan", OPT_BE16, NTUPLE_FLAG_VLAN,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.vlan_tci),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.vlan_tci) },
+	{ "user-def", OPT_BE64, NTUPLE_FLAG_UDEF,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.data),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.data) },
+	{ "dst-mac", OPT_MAC, NFC_FLAG_MAC_ADDR,
+	  offsetof(struct ethtool_rx_flow_spec, h_ext.h_dest),
+	  offsetof(struct ethtool_rx_flow_spec, m_ext.h_dest) },
+};
+
 static const struct rule_opts rule_nfc_ether[] = {
 	{ "src", OPT_MAC, NFC_FLAG_SADDR,
 	  offsetof(struct ethtool_rx_flow_spec, h_u.ether_spec.h_source),
@@ -726,6 +909,14 @@ static int rxclass_get_ipv4(char *str, __be32 *val)
 	return 0;
 }
 
+static int rxclass_get_ipv6(char *str, __be32 *val)
+{
+	if (!inet_pton(AF_INET6, str, val))
+		return -1;
+
+	return 0;
+}
+
 static int rxclass_get_ether(char *str, unsigned char *val)
 {
 	unsigned int buf[ETH_ALEN];
@@ -851,6 +1042,16 @@ static int rxclass_get_val(char *str, unsigned char *p, u32 *flags,
 			*(__be32 *)&p[opt->moffset] = (__be32)mask;
 		break;
 	}
+	case OPT_IP6: {
+		__be32 val[4];
+		err = rxclass_get_ipv6(str, val);
+		if (err)
+			return -1;
+		memcpy(&p[opt->offset], val, sizeof(val));
+		if (opt->moffset >= 0)
+			memset(&p[opt->moffset], mask, sizeof(val));
+		break;
+	}
 	case OPT_MAC: {
 		unsigned char val[ETH_ALEN];
 		err = rxclass_get_ether(str, val);
@@ -950,6 +1151,17 @@ static int rxclass_get_mask(char *str, unsigned char *p,
 		*(__be32 *)&p[opt->moffset] = ~val;
 		break;
 	}
+	case OPT_IP6: {
+		__be32 val[4], *field;
+		int i;
+		err = rxclass_get_ipv6(str, val);
+		if (err)
+			return -1;
+		field = (__be32 *)&p[opt->moffset];
+		for (i = 0; i < 4; i++)
+			field[i] = ~val[i];
+		break;
+	}
 	case OPT_MAC: {
 		unsigned char val[ETH_ALEN];
 		int i;
@@ -996,7 +1208,19 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx,
 	else if (!strcmp(argp[0], "esp4"))
 		flow_type = ESP_V4_FLOW;
 	else if (!strcmp(argp[0], "ip4"))
-		flow_type = IP_USER_FLOW;
+		flow_type = IPV4_USER_FLOW;
+	else if (!strcmp(argp[0], "tcp6"))
+		flow_type = TCP_V6_FLOW;
+	else if (!strcmp(argp[0], "udp6"))
+		flow_type = UDP_V6_FLOW;
+	else if (!strcmp(argp[0], "sctp6"))
+		flow_type = SCTP_V6_FLOW;
+	else if (!strcmp(argp[0], "ah6"))
+		flow_type = AH_V6_FLOW;
+	else if (!strcmp(argp[0], "esp6"))
+		flow_type = ESP_V6_FLOW;
+	else if (!strcmp(argp[0], "ip6"))
+		flow_type = IPV6_USER_FLOW;
 	else if (!strcmp(argp[0], "ether"))
 		flow_type = ETHER_FLOW;
 	else
@@ -1014,10 +1238,25 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx,
 		options = rule_nfc_esp_ip4;
 		n_opts = ARRAY_SIZE(rule_nfc_esp_ip4);
 		break;
-	case IP_USER_FLOW:
+	case IPV4_USER_FLOW:
 		options = rule_nfc_usr_ip4;
 		n_opts = ARRAY_SIZE(rule_nfc_usr_ip4);
 		break;
+	case TCP_V6_FLOW:
+	case UDP_V6_FLOW:
+	case SCTP_V6_FLOW:
+		options = rule_nfc_tcp_ip6;
+		n_opts = ARRAY_SIZE(rule_nfc_tcp_ip6);
+		break;
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+		options = rule_nfc_esp_ip6;
+		n_opts = ARRAY_SIZE(rule_nfc_esp_ip6);
+		break;
+	case IPV6_USER_FLOW:
+		options = rule_nfc_usr_ip6;
+		n_opts = ARRAY_SIZE(rule_nfc_usr_ip6);
+		break;
 	case ETHER_FLOW:
 		options = rule_nfc_ether;
 		n_opts = ARRAY_SIZE(rule_nfc_ether);
@@ -1081,7 +1320,7 @@ int rxclass_parse_ruleopts(struct cmd_context *ctx,
 		}
 	}
 
-	if (flow_type == IP_USER_FLOW)
+	if (flow_type == IPV4_USER_FLOW)
 		fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
 	if (flags & (NTUPLE_FLAG_VLAN | NTUPLE_FLAG_UDEF | NTUPLE_FLAG_VETH))
 		fsp->flow_type |= FLOW_EXT;

^ permalink raw reply related

* [PATCH v2 ethtool 0/2] IPv6 RXNFC
From: Edward Cree @ 2016-03-17 19:09 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev

This series adds support for steering of IPv6 receive flows.

Changes since v1:
* Fixed and simplified IPv6 address and mask parsing
* Made help text / man page more consistent
* Dropped ethtool-copy.h patch as upstream is now newer

Edward Cree (2):
  Add IPv6 support to NFC
  Documentation for IPv6 NFC

 ethtool.8.in |  29 +++++--
 ethtool.c    |  25 +++++-
 rxclass.c    | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 298 insertions(+), 24 deletions(-)

^ permalink raw reply

* [PATCH net] net: bcmgenet: fix dma api length mismatch
From: Eric Dumazet @ 2016-03-17 18:57 UTC (permalink / raw)
  To: Florian Fainelli, David Miller; +Cc: netdev, opendmb
In-Reply-To: <56EAE2A8.5000206@gmail.com>

From: Eric Dumazet <edumazet@google.com>

When un-mapping skb->data in __bcmgenet_tx_reclaim(),
we must use the length that was used in original dma_map_single(),
instead of skb->len that might be bigger (includes the frags)

We simply can store skb_len into tx_cb_ptr->dma_len and use it
at unmap time.

Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file")
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 drivers/net/ethernet/broadcom/genet/bcmgenet.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index d7e01a7..6746fd0 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1197,7 +1197,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
 			dev->stats.tx_bytes += tx_cb_ptr->skb->len;
 			dma_unmap_single(&dev->dev,
 					 dma_unmap_addr(tx_cb_ptr, dma_addr),
-					 tx_cb_ptr->skb->len,
+					 dma_unmap_len(tx_cb_ptr, dma_len),
 					 DMA_TO_DEVICE);
 			bcmgenet_free_cb(tx_cb_ptr);
 		} else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
@@ -1308,7 +1308,7 @@ static int bcmgenet_xmit_single(struct net_device *dev,
 	}
 
 	dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping);
-	dma_unmap_len_set(tx_cb_ptr, dma_len, skb->len);
+	dma_unmap_len_set(tx_cb_ptr, dma_len, skb_len);
 	length_status = (skb_len << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
 			(priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT) |
 			DMA_TX_APPEND_CRC;

^ permalink raw reply related

* Re: net/ppp: use-after-free in ppp_unregister_channel
From: Guillaume Nault @ 2016-03-17 18:30 UTC (permalink / raw)
  To: Baozeng Ding; +Cc: linux-kernel, paulus, linux-ppp, netdev
In-Reply-To: <56e97869.6afe420a.80cd8.ffffde3d@mx.google.com>

On Wed, Mar 16, 2016 at 11:14:42PM +0800, Baozeng Ding wrote:
> Dear all,
> I've got the following use-after-free report while running syzkaller
> fuzzer. Unfortunately no reproducer. It was found in the Linux kernel
> version(4.4, on commit 9638685e32af961943b679fcb72d4ddd458eb18f).
> 
> ==================================================================
> BUG: KASAN: use-after-free in ppp_unregister_channel+0x372/0x3a0 at
> addr ffff880064e217e0
> Read of size 8 by task syz-executor/11581
> =============================================================================
> BUG net_namespace (Not tainted): kasan: bad access detected
> -----------------------------------------------------------------------------
> 
> Disabling lock debugging due to kernel taint
> INFO: Allocated in copy_net_ns+0x6b/0x1a0 age=92569 cpu=3 pid=6906
> [<      none      >] ___slab_alloc+0x4c7/0x500 kernel/mm/slub.c:2440
> [<      none      >] __slab_alloc+0x4c/0x90 kernel/mm/slub.c:2469
> [<     inline     >] slab_alloc_node kernel/mm/slub.c:2532
> [<     inline     >] slab_alloc kernel/mm/slub.c:2574
> [<      none      >] kmem_cache_alloc+0x23a/0x2b0 kernel/mm/slub.c:2579
> [<     inline     >] kmem_cache_zalloc kernel/include/linux/slab.h:597
> [<     inline     >] net_alloc kernel/net/core/net_namespace.c:325
> [<      none      >] copy_net_ns+0x6b/0x1a0 kernel/net/core/net_namespace.c:360
> [<      none      >] create_new_namespaces+0x2f6/0x610 kernel/kernel/nsproxy.c:95
> [<      none      >] copy_namespaces+0x297/0x320 kernel/kernel/nsproxy.c:150
> [<      none      >] copy_process.part.35+0x1bf4/0x5760 kernel/kernel/fork.c:1451
> [<     inline     >] copy_process kernel/kernel/fork.c:1274
> [<      none      >] _do_fork+0x1bc/0xcb0 kernel/kernel/fork.c:1723
> [<     inline     >] SYSC_clone kernel/kernel/fork.c:1832
> [<      none      >] SyS_clone+0x37/0x50 kernel/kernel/fork.c:1826
> [<      none      >] entry_SYSCALL_64_fastpath+0x16/0x7a kernel/arch/x86/entry/entry_64.S:185
> 
> INFO: Freed in net_drop_ns+0x67/0x80 age=575 cpu=2 pid=2631
> [<      none      >] __slab_free+0x1fc/0x320 kernel/mm/slub.c:2650
> [<     inline     >] slab_free kernel/mm/slub.c:2805
> [<      none      >] kmem_cache_free+0x2a0/0x330 kernel/mm/slub.c:2814
> [<     inline     >] net_free kernel/net/core/net_namespace.c:341
> [<      none      >] net_drop_ns+0x67/0x80 kernel/net/core/net_namespace.c:348
> [<      none      >] cleanup_net+0x4e5/0x600 kernel/net/core/net_namespace.c:448
> [<      none      >] process_one_work+0x794/0x1440 kernel/kernel/workqueue.c:2036
> [<      none      >] worker_thread+0xdb/0xfc0 kernel/kernel/workqueue.c:2170
> [<      none      >] kthread+0x23f/0x2d0 kernel/drivers/block/aoe/aoecmd.c:1303
> [<      none      >] ret_from_fork+0x3f/0x70 kernel/arch/x86/entry/entry_64.S:468
> INFO: Slab 0xffffea0001938800 objects=3 used=0 fp=0xffff880064e20000
> flags=0x5fffc0000004080
> INFO: Object 0xffff880064e20000 @offset=0 fp=0xffff880064e24200
> 
> CPU: 1 PID: 11581 Comm: syz-executor Tainted: G    B           4.4.0+
> #5
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
>  00000000ffffffff ffff8800662c7790 ffffffff8292049d ffff88003e36a300
>  ffff880064e20000 ffff880064e20000 ffff8800662c77c0 ffffffff816f2054
>  ffff88003e36a300 ffffea0001938800 ffff880064e20000 0000000000000000
> Call Trace:
>  [<     inline     >] __dump_stack kernel/lib/dump_stack.c:15
>  [<ffffffff8292049d>] dump_stack+0x6f/0xa2 kernel/lib/dump_stack.c:50
>  [<ffffffff816f2054>] print_trailer+0xf4/0x150 kernel/mm/slub.c:654
>  [<ffffffff816f875f>] object_err+0x2f/0x40 kernel/mm/slub.c:661
>  [<     inline     >] print_address_description kernel/mm/kasan/report.c:138
>  [<ffffffff816fb0c5>] kasan_report_error+0x215/0x530 kernel/mm/kasan/report.c:236
>  [<     inline     >] kasan_report kernel/mm/kasan/report.c:259
>  [<ffffffff816fb4de>] __asan_report_load8_noabort+0x3e/0x40 kernel/mm/kasan/report.c:280
>  [<     inline     >] ? ppp_pernet kernel/include/linux/compiler.h:218
>  [<ffffffff83ad71b2>] ? ppp_unregister_channel+0x372/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392
>  [<     inline     >] ppp_pernet kernel/include/linux/compiler.h:218
>  [<ffffffff83ad71b2>] ppp_unregister_channel+0x372/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392
>  [<     inline     >] ? ppp_pernet kernel/drivers/net/ppp/ppp_generic.c:293
>  [<ffffffff83ad6f26>] ? ppp_unregister_channel+0xe6/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392
>  [<ffffffff83ae18f3>] ppp_asynctty_close+0xa3/0x130 kernel/drivers/net/ppp/ppp_async.c:241
>  [<ffffffff83ae1850>] ? async_lcp_peek+0x5b0/0x5b0 kernel/drivers/net/ppp/ppp_async.c:1000
>  [<ffffffff82c33239>] tty_ldisc_close.isra.1+0x99/0xe0 kernel/drivers/tty/tty_ldisc.c:478
>  [<ffffffff82c332c0>] tty_ldisc_kill+0x40/0x170 kernel/drivers/tty/tty_ldisc.c:744
>  [<ffffffff82c34943>] tty_ldisc_release+0x1b3/0x260 kernel/drivers/tty/tty_ldisc.c:772
>  [<ffffffff82c1ef21>] tty_release+0xac1/0x13e0 kernel/drivers/tty/tty_io.c:1901
>  [<ffffffff82c1e460>] ? release_tty+0x320/0x320 kernel/drivers/tty/tty_io.c:1688
>  [<ffffffff8174de36>] __fput+0x236/0x780 kernel/fs/file_table.c:208
>  [<ffffffff8174e405>] ____fput+0x15/0x20 kernel/fs/file_table.c:244
>  [<ffffffff813595ab>] task_work_run+0x16b/0x200 kernel/kernel/task_work.c:115
>  [<     inline     >] exit_task_work kernel/include/linux/task_work.h:21
>  [<ffffffff81307105>] do_exit+0x8b5/0x2c60 kernel/kernel/exit.c:750
>  [<ffffffff813fdd20>] ? debug_check_no_locks_freed+0x290/0x290 kernel/kernel/locking/lockdep.c:4123
>  [<ffffffff81306850>] ? mm_update_next_owner+0x6f0/0x6f0 kernel/kernel/exit.c:357
>  [<ffffffff813215e6>] ? __dequeue_signal+0x136/0x470 kernel/kernel/signal.c:550
>  [<ffffffff8132067b>] ? recalc_sigpending_tsk+0x13b/0x180 kernel/kernel/signal.c:145
>  [<ffffffff81309628>] do_group_exit+0x108/0x330 kernel/kernel/exit.c:880
>  [<ffffffff8132b9d4>] get_signal+0x5e4/0x14f0 kernel/kernel/signal.c:2307
>  [<     inline     >] ? kretprobe_table_lock kernel/kernel/kprobes.c:1113
>  [<ffffffff8151d355>] ? kprobe_flush_task+0xb5/0x450 kernel/kernel/kprobes.c:1158
>  [<ffffffff8115f7d3>] do_signal+0x83/0x1c90 kernel/arch/x86/kernel/signal.c:712
>  [<ffffffff8151d2a0>] ? recycle_rp_inst+0x310/0x310 kernel/include/linux/list.h:655
>  [<ffffffff8115f750>] ? setup_sigcontext+0x780/0x780 kernel/arch/x86/kernel/signal.c:165
>  [<ffffffff81380864>] ? finish_task_switch+0x424/0x5f0 kernel/kernel/sched/core.c:2692
>  [<     inline     >] ? finish_lock_switch kernel/kernel/sched/sched.h:1099
>  [<ffffffff81380560>] ? finish_task_switch+0x120/0x5f0 kernel/kernel/sched/core.c:2678
>  [<     inline     >] ? context_switch kernel/kernel/sched/core.c:2807
>  [<ffffffff85d794e9>] ? __schedule+0x919/0x1bd0 kernel/kernel/sched/core.c:3283
>  [<ffffffff81003901>] exit_to_usermode_loop+0xf1/0x1a0 kernel/arch/x86/entry/common.c:247
>  [<     inline     >] prepare_exit_to_usermode kernel/arch/x86/entry/common.c:282
>  [<ffffffff810062ef>] syscall_return_slowpath+0x19f/0x210 kernel/arch/x86/entry/common.c:344
>  [<ffffffff85d88022>] int_ret_from_sys_call+0x25/0x9f kernel/arch/x86/entry/entry_64.S:281

A network namespace has been removed while a ppp_async channel was
still registered in it. Then, unregistering this channel triggered the
bug because ppp_unregister_channel() tried to access its per-netns data
in the defunct namespace.

This scenario can happen at least with ppp_async and ppp_synctty, where
the userspace program and the PPP channel it handles can leave in
separate namespaces.

Thanks for the report, I can reproduce the bug and will work on a fix.

Guillaume

^ permalink raw reply

* Re: Extreme slowness in IPIP tunnel when routing through kernel 3.18 and later
From: Jesse Gross @ 2016-03-17 18:27 UTC (permalink / raw)
  To: Patrick Boutilier; +Cc: Linux Kernel Network Developers
In-Reply-To: <56EAB8F3.7060802@ednet.ns.ca>

On Thu, Mar 17, 2016 at 7:02 AM, Patrick Boutilier <boutilpj@ednet.ns.ca> wrote:
> I have an IPIP tunnel setup between two hosts in different buildings. The
> Linux router they route through causes extreme slowness in the tunnel when
> running kernels from 3.18 on . tcpdump shows many cksum errors which don't
> show up in the 3.17 and earlier kernels. Speed goes back to normal when
> rx-checksumming and tx-checksumming are turned off using ethtool on the
> Linux router . Would this be an effect of bulk network packet transmission
> that was introduced in 3.18 or some other issue?

I just sent out a likely fix, would you mind testing it?
https://patchwork.ozlabs.org/patch/599213/

^ permalink raw reply

* [PATCH net 3/3] tunnels: Remove encapsulation offloads on decap.
From: Jesse Gross @ 2016-03-17 18:25 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Ramu Ramamurthy
In-Reply-To: <1458239136-37814-1-git-send-email-jesse@kernel.org>

If a packet is either locally encapsulated or processed through GRO
it is marked with the offloads that it requires. However, when it is
decapsulated these tunnel offload indications are not removed. This
means that if we receive an encapsulated TCP packet, aggregate it with
GRO, decapsulate, and retransmit the resulting frame on a NIC that does
not support encapsulation, we won't be able to take advantage of hardware
offloads even though it is just a simple TCP packet at this point.

This fixes the problem by stripping off encapsulation offload indications
when packets are decapsulated.

Reported-by: Ramu Ramamurthy <sramamur@linux.vnet.ibm.com>
Fixes: 68c33163 ("v4 GRE: Add TCP segmentation offload for GRE")
Signed-off-by: Jesse Gross <jesse@kernel.org>
---
 include/net/ip_tunnels.h  | 16 ++++++++++++++++
 net/ipv4/fou.c            | 13 +++++++++++--
 net/ipv4/ip_tunnel_core.c |  3 ++-
 net/ipv6/sit.c            |  6 ++++--
 4 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 5dc2e45..7ac8e4b 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -298,6 +298,22 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
 
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask);
 
+static inline int iptunnel_pull_offloads(struct sk_buff *skb)
+{
+	if (skb_is_gso(skb)) {
+		int err;
+
+		err = skb_unclone(skb, GFP_ATOMIC);
+		if (unlikely(err))
+			return err;
+		skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
+					       NETIF_F_GSO_SHIFT);
+	}
+
+	skb->encapsulation = 0;
+	return 0;
+}
+
 static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
 {
 	if (pkt_len > 0) {
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 7804842..a0586b4 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -48,7 +48,7 @@ static inline struct fou *fou_from_sock(struct sock *sk)
 	return sk->sk_user_data;
 }
 
-static void fou_recv_pull(struct sk_buff *skb, size_t len)
+static int fou_recv_pull(struct sk_buff *skb, size_t len)
 {
 	struct iphdr *iph = ip_hdr(skb);
 
@@ -59,6 +59,7 @@ static void fou_recv_pull(struct sk_buff *skb, size_t len)
 	__skb_pull(skb, len);
 	skb_postpull_rcsum(skb, udp_hdr(skb), len);
 	skb_reset_transport_header(skb);
+	return iptunnel_pull_offloads(skb);
 }
 
 static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
@@ -68,9 +69,14 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
 	if (!fou)
 		return 1;
 
-	fou_recv_pull(skb, sizeof(struct udphdr));
+	if (fou_recv_pull(skb, sizeof(struct udphdr)))
+		goto drop;
 
 	return -fou->protocol;
+
+drop:
+	kfree_skb(skb);
+	return 0;
 }
 
 static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
@@ -170,6 +176,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
 	__skb_pull(skb, sizeof(struct udphdr) + hdrlen);
 	skb_reset_transport_header(skb);
 
+	if (iptunnel_pull_offloads(skb))
+		goto drop;
+
 	return -guehdr->proto_ctype;
 
 drop:
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index eaca244..ee4827e 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -114,7 +114,8 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto,
 	skb->vlan_tci = 0;
 	skb_set_queue_mapping(skb, 0);
 	skb_scrub_packet(skb, xnet);
-	return 0;
+
+	return iptunnel_pull_offloads(skb);
 }
 EXPORT_SYMBOL_GPL(iptunnel_pull_header);
 
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index f45b8ff..8338430 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -681,14 +681,16 @@ static int ipip6_rcv(struct sk_buff *skb)
 		skb->mac_header = skb->network_header;
 		skb_reset_network_header(skb);
 		IPCB(skb)->flags = 0;
-		skb->protocol = htons(ETH_P_IPV6);
+		skb->dev = tunnel->dev;
 
 		if (packet_is_spoofed(skb, iph, tunnel)) {
 			tunnel->dev->stats.rx_errors++;
 			goto out;
 		}
 
-		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
+		if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6),
+		    !net_eq(tunnel->net, dev_net(tunnel->dev))))
+			goto out;
 
 		err = IP_ECN_decapsulate(iph, skb);
 		if (unlikely(err)) {
-- 
2.5.0

^ permalink raw reply related

* [PATCH net 2/3] tunnels: Don't apply GRO to multiple layers of encapsulation.
From: Jesse Gross @ 2016-03-17 18:25 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <1458239136-37814-1-git-send-email-jesse@kernel.org>

When drivers express support for TSO of encapsulated packets, they
only mean that they can do it for one layer of encapsulation.
Supporting additional levels would mean updating, at a minimum,
more IP length fields and they are unaware of this.

No encapsulation device expresses support for handling offloaded
encapsulated packets, so we won't generate these types of frames
in the transmit path. However, GRO doesn't have a check for
multiple levels of encapsulation and will attempt to build them.

UDP tunnel GRO actually does prevent this situation but it only
handles multiple UDP tunnels stacked on top of each other. This
generalizes that solution to prevent any kind of tunnel stacking
that would cause problems.

Fixes: bf5a755f ("net-gre-gro: Add GRE support to the GRO stack")
Signed-off-by: Jesse Gross <jesse@kernel.org>
---
 include/linux/netdevice.h |  4 ++--
 net/core/dev.c            |  2 +-
 net/ipv4/af_inet.c        | 15 ++++++++++++++-
 net/ipv4/gre_offload.c    |  5 +++++
 net/ipv4/udp_offload.c    |  6 +++---
 net/ipv6/ip6_offload.c    | 15 ++++++++++++++-
 6 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index be693b3..f9eebd5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2096,8 +2096,8 @@ struct napi_gro_cb {
 	/* This is non-zero if the packet may be of the same flow. */
 	u8	same_flow:1;
 
-	/* Used in udp_gro_receive */
-	u8	udp_mark:1;
+	/* Used in tunnel GRO receive */
+	u8	encap_mark:1;
 
 	/* GRO checksum is valid */
 	u8	csum_valid:1;
diff --git a/net/core/dev.c b/net/core/dev.c
index edb7179..43c74ca 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4438,7 +4438,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
 		NAPI_GRO_CB(skb)->same_flow = 0;
 		NAPI_GRO_CB(skb)->flush = 0;
 		NAPI_GRO_CB(skb)->free = 0;
-		NAPI_GRO_CB(skb)->udp_mark = 0;
+		NAPI_GRO_CB(skb)->encap_mark = 0;
 		NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
 		/* Setup for GRO checksum validation */
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 9659233..0fefba6 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1380,6 +1380,19 @@ out:
 	return pp;
 }
 
+static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
+					 struct sk_buff *skb)
+{
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return inet_gro_receive(head, skb);
+}
+
 #define SECONDS_PER_DAY	86400
 
 /* inet_current_timestamp - Return IP network timestamp
@@ -1682,7 +1695,7 @@ static struct packet_offload ip_packet_offload __read_mostly = {
 static const struct net_offload ipip_offload = {
 	.callbacks = {
 		.gso_segment	= inet_gso_segment,
-		.gro_receive	= inet_gro_receive,
+		.gro_receive	= ipip_gro_receive,
 		.gro_complete	= ipip_gro_complete,
 	},
 };
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 540866d..dd03161 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -126,6 +126,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
 	struct packet_offload *ptype;
 	__be16 type;
 
+	if (NAPI_GRO_CB(skb)->encap_mark)
+		goto out;
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
 	off = skb_gro_offset(skb);
 	hlen = off + sizeof(*greh);
 	greh = skb_gro_header_fast(skb, off);
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 8a3405a..8007f73 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -311,14 +311,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
 	unsigned int off = skb_gro_offset(skb);
 	int flush = 1;
 
-	if (NAPI_GRO_CB(skb)->udp_mark ||
+	if (NAPI_GRO_CB(skb)->encap_mark ||
 	    (skb->ip_summed != CHECKSUM_PARTIAL &&
 	     NAPI_GRO_CB(skb)->csum_cnt == 0 &&
 	     !NAPI_GRO_CB(skb)->csum_valid))
 		goto out;
 
-	/* mark that this skb passed once through the udp gro layer */
-	NAPI_GRO_CB(skb)->udp_mark = 1;
+	/* mark that this skb passed once through the tunnel gro layer */
+	NAPI_GRO_CB(skb)->encap_mark = 1;
 
 	rcu_read_lock();
 	uo_priv = rcu_dereference(udp_offload_base);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index eeca943..82e9f30 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -258,6 +258,19 @@ out:
 	return pp;
 }
 
+static struct sk_buff **sit_gro_receive(struct sk_buff **head,
+					struct sk_buff *skb)
+{
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return ipv6_gro_receive(head, skb);
+}
+
 static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	const struct net_offload *ops;
@@ -302,7 +315,7 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
 static const struct net_offload sit_offload = {
 	.callbacks = {
 		.gso_segment	= ipv6_gso_segment,
-		.gro_receive    = ipv6_gro_receive,
+		.gro_receive    = sit_gro_receive,
 		.gro_complete   = sit_gro_complete,
 	},
 };
-- 
2.5.0

^ permalink raw reply related

* [PATCH net 1/3] ipip: Properly mark ipip GRO packets as encapsulated.
From: Jesse Gross @ 2016-03-17 18:25 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Patrick Boutilier

ipip encapsulated packets can be merged together by GRO but the result
does not have the proper GSO type set or even marked as being
encapsulated at all. Later retransmission of these packets will likely
fail if the device does not support ipip offloads. This is similar to
the issue resolved in IPv6 sit in feec0cb3
("ipv6: gro: support sit protocol").

Reported-by: Patrick Boutilier <boutilpj@ednet.ns.ca>
Fixes: 9667e9bb ("ipip: Add gro callbacks to ipip offload")
Signed-off-by: Jesse Gross <jesse@kernel.org>
---
 net/ipv4/af_inet.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 0cc923f..9659233 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1448,6 +1448,13 @@ out_unlock:
 	return err;
 }
 
+static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
+{
+	skb->encapsulation = 1;
+	skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
+	return inet_gro_complete(skb, nhoff);
+}
+
 int inet_ctl_sock_create(struct sock **sk, unsigned short family,
 			 unsigned short type, unsigned char protocol,
 			 struct net *net)
@@ -1676,7 +1683,7 @@ static const struct net_offload ipip_offload = {
 	.callbacks = {
 		.gso_segment	= inet_gso_segment,
 		.gro_receive	= inet_gro_receive,
-		.gro_complete	= inet_gro_complete,
+		.gro_complete	= ipip_gro_complete,
 	},
 };
 
-- 
2.5.0

^ permalink raw reply related

* Re: [PATCH v2 1/2] Revert "vsock: Fix blocking ops call in prepare_to_wait"
From: Laura Abbott @ 2016-03-17 18:07 UTC (permalink / raw)
  To: Claudio Imbrenda, davem; +Cc: labbott, netdev, linux-kernel
In-Reply-To: <1458231156-18845-2-git-send-email-imbrenda@linux.vnet.ibm.com>

On 03/17/2016 09:12 AM, Claudio Imbrenda wrote:
> This reverts commit 5988818008257ca42010d6b43a3e0e48afec9898 ("vsock: Fix
> blocking ops call in prepare_to_wait")
>

I don't think having this as a separate patch does a lot of good. You
can probably fold this into the next patch with a note saying that
you are removing this broken behavior. If you really want this to
be separate, please add a description of why this is being reverted.

Thanks,
Laura

> Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
> ---
>   net/vmw_vsock/af_vsock.c | 19 +++++++++++++------
>   1 file changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> index bbe65dc..7fd1220 100644
> --- a/net/vmw_vsock/af_vsock.c
> +++ b/net/vmw_vsock/af_vsock.c
> @@ -1557,6 +1557,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
>   	if (err < 0)
>   		goto out;
>
> +	prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
> +
>   	while (total_written < len) {
>   		ssize_t written;
>
> @@ -1576,9 +1578,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
>   				goto out_wait;
>
>   			release_sock(sk);
> -			prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
>   			timeout = schedule_timeout(timeout);
> -			finish_wait(sk_sleep(sk), &wait);
>   			lock_sock(sk);
>   			if (signal_pending(current)) {
>   				err = sock_intr_errno(timeout);
> @@ -1588,6 +1588,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
>   				goto out_wait;
>   			}
>
> +			prepare_to_wait(sk_sleep(sk), &wait,
> +					TASK_INTERRUPTIBLE);
>   		}
>
>   		/* These checks occur both as part of and after the loop
> @@ -1633,6 +1635,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
>   out_wait:
>   	if (total_written > 0)
>   		err = total_written;
> +	finish_wait(sk_sleep(sk), &wait);
>   out:
>   	release_sock(sk);
>   	return err;
> @@ -1713,6 +1716,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>   	if (err < 0)
>   		goto out;
>
> +	prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
>
>   	while (1) {
>   		s64 ready = vsock_stream_has_data(vsk);
> @@ -1723,7 +1727,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>   			 */
>
>   			err = -ENOMEM;
> -			goto out;
> +			goto out_wait;
>   		} else if (ready > 0) {
>   			ssize_t read;
>
> @@ -1746,7 +1750,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>   					vsk, target, read,
>   					!(flags & MSG_PEEK), &recv_data);
>   			if (err < 0)
> -				goto out;
> +				goto out_wait;
>
>   			if (read >= target || flags & MSG_PEEK)
>   				break;
> @@ -1769,9 +1773,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>   				break;
>
>   			release_sock(sk);
> -			prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
>   			timeout = schedule_timeout(timeout);
> -			finish_wait(sk_sleep(sk), &wait);
>   			lock_sock(sk);
>
>   			if (signal_pending(current)) {
> @@ -1781,6 +1783,9 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>   				err = -EAGAIN;
>   				break;
>   			}
> +
> +			prepare_to_wait(sk_sleep(sk), &wait,
> +					TASK_INTERRUPTIBLE);
>   		}
>   	}
>
> @@ -1811,6 +1816,8 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>   		err = copied;
>   	}
>
> +out_wait:
> +	finish_wait(sk_sleep(sk), &wait);
>   out:
>   	release_sock(sk);
>   	return err;
>

^ permalink raw reply

* Re: [PATCH] net: phy: at803x: Add support to control PHY LEDs
From: Vishal Thanki @ 2016-03-17 18:07 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Florian Fainelli, Matus Ujhelyi, netdev
In-Reply-To: <20160317175152.GG26019@lunn.ch>

> 
> They might not be on/off controllable individually, but you can often
> set them to show Packet RX, Packet TX, Link, speed, etc, in a
> reasonably flexible way. So you could have LED triggers mapping to
> these functionalities. The user can then pick the trigger for the LED.
> 
> Actually, the data sheet says:
> 
> 2.3.4 LED Interface
> 
> The LED interface can either be controlled by the PHY or controlled
> manually, independent of the state of the PHY. Two status LEDs are
> available. These can be used to indicate operation speed, and link
> status. The LEDs can be programmed to different status functions from
> their default value. They can also be controlled directly from the MII
> register interface.
> 
> So maybe you can control the on/off state.
> 

I need to explore more on LED subsystem. Thank you for your suggestions
and input.

Thanks,
Vishal

>    Andrew

^ permalink raw reply

* Re: [v6, 3/5] dt: move guts devicetree doc out of powerpc directory
From: Rob Herring @ 2016-03-17 17:57 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Yangbo Lu, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linuxppc-dev, linux-clk,
	linux-i2c@vger.kernel.org, Linux IOMMU, netdev,
	linux-mmc@vger.kernel.org, scott.wood, Russell King,
	Jochen Friedrich, Joerg Roedel, Claudiu Manoil, Ulf Hansson,
	Bhupesh Sharma, Zhao Qiang, Kumar Gala, Santosh Shilimkar
In-Reply-To: <4107975.rId64mooHz@wuerfel>

On Thu, Mar 17, 2016 at 12:11 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 17 March 2016 12:06:40 Rob Herring wrote:
>> > diff --git a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt b/Documentation/devicetree/bindings/soc/fsl/guts.txt
>> > similarity index 91%
>> > rename from Documentation/devicetree/bindings/powerpc/fsl/guts.txt
>> > rename to Documentation/devicetree/bindings/soc/fsl/guts.txt
>> > index b71b203..07adca9 100644
>> > --- a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
>> > +++ b/Documentation/devicetree/bindings/soc/fsl/guts.txt
>> > @@ -25,6 +25,9 @@ Recommended properties:
>> >   - fsl,liodn-bits : Indicates the number of defined bits in the LIODN
>> >     registers, for those SOCs that have a PAMU device.
>> >
>> > + - little-endian : Indicates that the global utilities block is little
>> > +   endian. The default is big endian.
>>
>> The default is "the native endianness of the system".
>
> This may be what is currently documented, but not what we are doing
> in practice, as there is no "native endianess" for either PowerPC or
> ARM -- both allow running big-endian or little-endian kernels and the
> device registers are fixed.

Notice I said system, not architecture. The way the device registers
are fixed is what I mean by native endianness.

If the purpose of adding this property now is to support GUTS on the
ARM SoCs, then I'd argue using this property is probably wrong. If the
PPC systems are designed with BE device registers and ARM systems with
LE, then this property is not needed.

> I think the property here is fine.

Unless you have studied the FSL ARM based SoCs, then there is not
enough information here to tell.

Rob

^ permalink raw reply

* Re: [PATCH] net: phy: at803x: Add support to control PHY LEDs
From: Andrew Lunn @ 2016-03-17 17:51 UTC (permalink / raw)
  To: Vishal Thanki; +Cc: Florian Fainelli, Matus Ujhelyi, netdev
In-Reply-To: <CAC3a_SD=chB8pPpdRm8scztJ4592J26_PmhbUkLmbE3=DCmX-w@mail.gmail.com>

> I agree with the idea of making a generic callback in phy_driver so
> that other PHYs
> can use it. However I think these LEDs are tightly coupled with PHYs and it
> would not make much sense to expose them via LED subsystem as they
> cannot be controlled individually IMHO.

They might not be on/off controllable individually, but you can often
set them to show Packet RX, Packet TX, Link, speed, etc, in a
reasonably flexible way. So you could have LED triggers mapping to
these functionalities. The user can then pick the trigger for the LED.

Actually, the data sheet says:

2.3.4 LED Interface

The LED interface can either be controlled by the PHY or controlled
manually, independent of the state of the PHY. Two status LEDs are
available. These can be used to indicate operation speed, and link
status. The LEDs can be programmed to different status functions from
their default value. They can also be controlled directly from the MII
register interface.

So maybe you can control the on/off state.

   Andrew

^ permalink raw reply

* Re: [PATCH] net: phy: at803x: Add support to control PHY LEDs
From: Vishal Thanki @ 2016-03-17 17:32 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Andrew Lunn, Matus Ujhelyi, netdev
In-Reply-To: <56EAE277.4050109@gmail.com>

On Thu, Mar 17, 2016 at 5:59 PM, Florian Fainelli <f.fainelli@gmail.com> wrote:
> On 17/03/16 07:50, Andrew Lunn wrote:
>> On Thu, Mar 17, 2016 at 02:59:07PM +0100, Vishal Thanki wrote:
>>> The LEDs can be turned on and off by a sysfs interface
>>> now. Write 0 to "led_enable" file to turn off the LEDs
>>> and write 1 to turn on. The support is experimental
>>> and can be enabled by kernel configuration option.
>>>
>>> Signed-off-by: Vishal Thanki <vishalthanki@gmail.com>
>>> ---
>>>  drivers/net/phy/Kconfig  |  7 +++++
>>>  drivers/net/phy/at803x.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
>>
>> Hi Vishal
>>
>> This solution seems specific to the at803. You should be thinking of a
>> generic solution that all PHYs can use. eg add a new callback function
>> to phy_driver, and put the sysfs handling code in phylib.
>
> Indeed, maybe we should be considering using the existing LEDS subsystem
> (drivers/leds/*) to expose the PHY LEDs to user-space in a standard way?
> --

I agree with the idea of making a generic callback in phy_driver so
that other PHYs
can use it. However I think these LEDs are tightly coupled with PHYs and it
would not make much sense to expose them via LED subsystem as they
cannot be controlled individually IMHO.

> Florian

^ permalink raw reply

* Re: [Codel] [RFCv2 0/3] mac80211: implement fq codel
From: Rick Jones @ 2016-03-17 17:24 UTC (permalink / raw)
  To: Dave Taht, Michal Kazior
  Cc: Network Development, linux-wireless,
	ath10k-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Jasmine Strong,
	codel-JXvr2/1DY2fm6VMwtOF2vx4hnT+Y9+D1@public.gmane.org,
	make-wifi-fast-JXvr2/1DY2fm6VMwtOF2vx4hnT+Y9+D1
In-Reply-To: <CAA93jw7TuBLVi9k-+2=J27j-Qs+sS3UNaQNTMF9D2MQ13fQY9A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 03/17/2016 10:00 AM, Dave Taht wrote:
> netperf's udp_rr is not how much traffic conventionally behaves. It
> doesn't do tcp slow start or congestion control in particular...

Nor would one expect it to need to, unless one were using "burst mode" 
to have more than one transaction inflight at one time.

And unless one uses the test-specific -e option to provide a very crude 
retransmission mechanism based on a socket read timeout, neither does 
UDP_RR recover from lost datagrams.

happy benchmarking,

rick jones
http://www.netperf.org/
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [patch net-next RFC 13/13] mlxsw: spectrum: Implement shared buffer configuration
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Implement previously introduced devlink shared buffer API. In mlxsw that
is done utilizing registers SBPR, SBCM and SBPM.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |   8 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     |  21 +++
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 161 ++++++++++++++++++++-
 3 files changed, 189 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 324848d..60fc109 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2136,6 +2136,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 
 err_switchdev_init:
 err_lag_init:
+	mlxsw_sp_buffers_fini(mlxsw_sp);
 err_buffers_init:
 err_flood_init:
 	mlxsw_sp_traps_fini(mlxsw_sp);
@@ -2150,6 +2151,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
 {
 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
 
+	mlxsw_sp_buffers_fini(mlxsw_sp);
 	mlxsw_sp_switchdev_fini(mlxsw_sp);
 	mlxsw_sp_traps_fini(mlxsw_sp);
 	mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
@@ -2200,6 +2202,12 @@ static struct mlxsw_driver mlxsw_sp_driver = {
 	.fini			= mlxsw_sp_fini,
 	.port_split		= mlxsw_sp_port_split,
 	.port_unsplit		= mlxsw_sp_port_unsplit,
+	.sb_pool_get		= mlxsw_sp_sb_pool_get,
+	.sb_pool_set		= mlxsw_sp_sb_pool_set,
+	.sb_port_pool_get	= mlxsw_sp_sb_port_pool_get,
+	.sb_port_pool_set	= mlxsw_sp_sb_port_pool_set,
+	.sb_tc_pool_bind_get	= mlxsw_sp_sb_tc_pool_bind_get,
+	.sb_tc_pool_bind_set	= mlxsw_sp_sb_tc_pool_bind_set,
 	.txhdr_construct	= mlxsw_sp_txhdr_construct,
 	.txhdr_len		= MLXSW_TXHDR_LEN,
 	.profile		= &mlxsw_sp_config_profile,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index ed3c871..4c3d8a7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -272,7 +272,28 @@ enum mlxsw_sp_flood_table {
 };
 
 int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_buffers_fini(struct mlxsw_sp *mlxsw_sp);
 int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port);
+int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core,
+			 unsigned int sb_index, u16 pool_index,
+			 struct devlink_sb_pool_info *pool_info);
+int mlxsw_sp_sb_pool_set(struct mlxsw_core *mlxsw_core,
+			 unsigned int sb_index, u16 pool_index, u32 size,
+			 enum devlink_sb_threshold_type threshold_type);
+int mlxsw_sp_sb_port_pool_get(struct mlxsw_core_port *mlxsw_core_port,
+			      unsigned int sb_index, u16 pool_index,
+			      u32 *p_threshold);
+int mlxsw_sp_sb_port_pool_set(struct mlxsw_core_port *mlxsw_core_port,
+			      unsigned int sb_index, u16 pool_index,
+			      u32 threshold);
+int mlxsw_sp_sb_tc_pool_bind_get(struct mlxsw_core_port *mlxsw_core_port,
+				 unsigned int sb_index, u16 tc_index,
+				 enum devlink_sb_pool_type pool_type,
+				 u16 *p_pool_index, u32 *p_threshold);
+int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port,
+				 unsigned int sb_index, u16 tc_index,
+				 enum devlink_sb_pool_type pool_type,
+				 u16 pool_index, u32 threshold);
 
 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index beca792..17f8564 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -470,6 +470,8 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp)
 	return 0;
 }
 
+#define MLXSW_SP_SB_SIZE (16 * 1024 * 1024)
+
 int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
 {
 	int err;
@@ -484,7 +486,16 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
 	if (err)
 		return err;
 
-	return 0;
+	return devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0,
+				   MLXSW_SP_SB_SIZE,
+				   MLXSW_SP_SB_POOL_COUNT,
+				   MLXSW_SP_SB_POOL_COUNT,
+				   MLXSW_SP_SB_TC_COUNT);
+}
+
+void mlxsw_sp_buffers_fini(struct mlxsw_sp *mlxsw_sp)
+{
+	devlink_sb_unregister(priv_to_devlink(mlxsw_sp->core), 0);
 }
 
 int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port)
@@ -501,3 +512,151 @@ int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
 	return err;
 }
+
+static u8 pool_get(u16 pool_index)
+{
+	return pool_index % MLXSW_SP_SB_POOL_COUNT;
+}
+
+static u16 pool_index_get(u8 pool, enum mlxsw_reg_sbxx_dir dir)
+{
+	u16 pool_index;
+
+	pool_index = pool;
+	if (dir == MLXSW_REG_SBXX_DIR_EGRESS)
+		pool_index += MLXSW_SP_SB_POOL_COUNT;
+	return pool_index;
+}
+
+static enum mlxsw_reg_sbxx_dir dir_get(u16 pool_index)
+{
+	return pool_index < MLXSW_SP_SB_POOL_COUNT ?
+	       MLXSW_REG_SBXX_DIR_INGRESS : MLXSW_REG_SBXX_DIR_EGRESS;
+}
+
+int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core,
+			 unsigned int sb_index, u16 pool_index,
+			 struct devlink_sb_pool_info *pool_info)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	u8 pool = pool_get(pool_index);
+	enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
+	struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
+
+	pool_info->pool_type = dir;
+	pool_info->size = pr->size * MLXSW_SP_SB_BYTES_PER_CELL;
+	pool_info->threshold_type = pr->mode;
+	return 0;
+}
+
+int mlxsw_sp_sb_pool_set(struct mlxsw_core *mlxsw_core,
+			 unsigned int sb_index, u16 pool_index, u32 size,
+			 enum devlink_sb_threshold_type threshold_type)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+	u8 pool = pool_get(pool_index);
+	enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
+	enum mlxsw_reg_sbpr_mode mode = threshold_type;
+	u32 pool_size = DIV_ROUND_UP(size, MLXSW_SP_SB_BYTES_PER_CELL);
+
+	return mlxsw_sp_sb_pr_write(mlxsw_sp, pool, dir, mode, pool_size);
+}
+
+static u32 mlxsw_sp_sb_threshold_out(struct mlxsw_sp *mlxsw_sp, u8 pool,
+				     enum mlxsw_reg_sbxx_dir dir, u32 max_buff)
+{
+	struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
+
+	if (pr->mode == MLXSW_REG_SBPR_MODE_DYNAMIC)
+		return max_buff;
+	return max_buff * MLXSW_SP_SB_BYTES_PER_CELL;
+}
+
+static u32 mlxsw_sp_sb_threshold_in(struct mlxsw_sp *mlxsw_sp, u8 pool,
+				    enum mlxsw_reg_sbxx_dir dir, u32 threshold)
+{
+	struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
+
+	if (pr->mode == MLXSW_REG_SBPR_MODE_DYNAMIC)
+		return threshold;
+	return DIV_ROUND_UP(threshold, MLXSW_SP_SB_BYTES_PER_CELL);
+}
+
+int mlxsw_sp_sb_port_pool_get(struct mlxsw_core_port *mlxsw_core_port,
+			      unsigned int sb_index, u16 pool_index,
+			      u32 *p_threshold)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port =
+			mlxsw_core_port_driver_priv(mlxsw_core_port);
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	u8 local_port = mlxsw_sp_port->local_port;
+	u8 pool = pool_get(pool_index);
+	enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
+	struct mlxsw_sp_sb_pm *pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port,
+						       pool, dir);
+
+	*p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, pool, dir,
+						 pm->max_buff);
+	return 0;
+}
+
+int mlxsw_sp_sb_port_pool_set(struct mlxsw_core_port *mlxsw_core_port,
+			      unsigned int sb_index, u16 pool_index,
+			      u32 threshold)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port =
+			mlxsw_core_port_driver_priv(mlxsw_core_port);
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	u8 local_port = mlxsw_sp_port->local_port;
+	u8 pool = pool_get(pool_index);
+	enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
+	u32 max_buff = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool, dir, threshold);
+
+	return mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, pool, dir,
+				    0, max_buff);
+}
+
+int mlxsw_sp_sb_tc_pool_bind_get(struct mlxsw_core_port *mlxsw_core_port,
+				 unsigned int sb_index, u16 tc_index,
+				 enum devlink_sb_pool_type pool_type,
+				 u16 *p_pool_index, u32 *p_threshold)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port =
+			mlxsw_core_port_driver_priv(mlxsw_core_port);
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	u8 local_port = mlxsw_sp_port->local_port;
+	u8 pg_buff = tc_index;
+	enum mlxsw_reg_sbxx_dir dir = pool_type;
+	struct mlxsw_sp_sb_cm *cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port,
+						       pg_buff, dir);
+
+	*p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, cm->pool, dir,
+						 cm->max_buff);
+	*p_pool_index = pool_index_get(cm->pool, pool_type);;
+	return 0;
+}
+
+int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port,
+				 unsigned int sb_index, u16 tc_index,
+				 enum devlink_sb_pool_type pool_type,
+				 u16 pool_index, u32 threshold)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port =
+			mlxsw_core_port_driver_priv(mlxsw_core_port);
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	u8 local_port = mlxsw_sp_port->local_port;
+	u8 pg_buff = tc_index;
+	enum mlxsw_reg_sbxx_dir dir = pool_type;
+	u8 pool = pool_index;
+	u32 max_buff = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool, dir, threshold);
+
+	if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS) {
+		if (pool < MLXSW_SP_SB_POOL_COUNT)
+			return -EINVAL;
+		pool -= MLXSW_SP_SB_POOL_COUNT;
+	} else if (pool >= MLXSW_SP_SB_POOL_COUNT) {
+		return -EINVAL;
+	}
+	return mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, pg_buff, dir,
+				    0, max_buff, pool);
+}
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 09/13] mlxsw: spectrum_buffers: Push out shared buffer register writes
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Pushed them into helper functions.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 54 ++++++++++++++++------
 1 file changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index fb5f787..cc40f4c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -40,6 +40,37 @@
 #include "port.h"
 #include "reg.h"
 
+static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u8 pool,
+				enum mlxsw_reg_sbxx_dir dir,
+				enum mlxsw_reg_sbpr_mode mode, u32 size)
+{
+	char sbpr_pl[MLXSW_REG_SBPR_LEN];
+
+	mlxsw_reg_sbpr_pack(sbpr_pl, pool, dir, mode, size);
+	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
+}
+
+static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+				u8 pg_buff, enum mlxsw_reg_sbxx_dir dir,
+				u32 min_buff, u32 max_buff, u8 pool)
+{
+	char sbcm_pl[MLXSW_REG_SBCM_LEN];
+
+	mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, dir,
+			    min_buff, max_buff, pool);
+	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
+}
+
+static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+				u8 pool, enum mlxsw_reg_sbxx_dir dir,
+				u32 min_buff, u32 max_buff)
+{
+	char sbpm_pl[MLXSW_REG_SBPM_LEN];
+
+	mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, min_buff, max_buff);
+	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl);
+}
+
 struct mlxsw_sp_pb {
 	u8 index;
 	u16 size;
@@ -129,7 +160,6 @@ static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = {
 
 static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
 {
-	char sbpr_pl[MLXSW_REG_SBPR_LEN];
 	int i;
 	int err;
 
@@ -137,9 +167,8 @@ static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
 		const struct mlxsw_sp_sb_pool *pool;
 
 		pool = &mlxsw_sp_sb_pools[i];
-		mlxsw_reg_sbpr_pack(sbpr_pl, pool->pool, pool->dir,
-				    pool->mode, pool->size);
-		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
+		err = mlxsw_sp_sb_pr_write(mlxsw_sp, pool->pool, pool->dir,
+					   pool->mode, pool->size);
 		if (err)
 			return err;
 	}
@@ -250,7 +279,6 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 				const struct mlxsw_sp_sb_cm *cms,
 				size_t cms_len)
 {
-	char sbcm_pl[MLXSW_REG_SBCM_LEN];
 	int i;
 	int err;
 
@@ -258,9 +286,9 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 		const struct mlxsw_sp_sb_cm *cm;
 
 		cm = &cms[i];
-		mlxsw_reg_sbcm_pack(sbcm_pl, local_port, cm->u.pg, cm->dir,
-				    cm->min_buff, cm->max_buff, cm->pool);
-		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
+		err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, cm->u.pg,
+					   cm->dir, cm->min_buff,
+					   cm->max_buff, cm->pool);
 		if (err)
 			return err;
 	}
@@ -318,7 +346,6 @@ static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
 
 static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
 {
-	char sbpm_pl[MLXSW_REG_SBPM_LEN];
 	int i;
 	int err;
 
@@ -326,11 +353,10 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
 		const struct mlxsw_sp_sb_pm *pm;
 
 		pm = &mlxsw_sp_sb_pms[i];
-		mlxsw_reg_sbpm_pack(sbpm_pl, mlxsw_sp_port->local_port,
-				    pm->pool, pm->dir,
-				    pm->min_buff, pm->max_buff);
-		err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core,
-				      MLXSW_REG(sbpm), sbpm_pl);
+		err = mlxsw_sp_sb_pm_write(mlxsw_sp_port->mlxsw_sp,
+					   mlxsw_sp_port->local_port,
+					   pm->pool, pm->dir,
+					   pm->min_buff, pm->max_buff);
 		if (err)
 			return err;
 	}
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 12/13] mlxsw: spectrum_buffers: Cache shared buffer configuration
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

In order to achieve faster dumping of current setting and also
for possibility to get pool mode without need to query hardware,
cache the configuration in driver.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     | 28 ++++++++
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 81 ++++++++++++++++------
 2 files changed, 89 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 22a5a94..ed3c871 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -99,6 +99,33 @@ static inline bool mlxsw_sp_fid_is_vfid(u16 fid)
 	return fid >= MLXSW_SP_VFID_BASE;
 }
 
+struct mlxsw_sp_sb_pr {
+	enum mlxsw_reg_sbpr_mode mode;
+	u32 size;
+};
+
+struct mlxsw_sp_sb_cm {
+	u32 min_buff;
+	u32 max_buff;
+	u8 pool;
+};
+
+struct mlxsw_sp_sb_pm {
+	u32 min_buff;
+	u32 max_buff;
+};
+
+#define MLXSW_SP_SB_POOL_COUNT	4
+#define MLXSW_SP_SB_TC_COUNT	8
+
+struct mlxsw_sp_sb {
+	struct mlxsw_sp_sb_pr prs[2][MLXSW_SP_SB_POOL_COUNT];
+	struct {
+		struct mlxsw_sp_sb_cm cms[2][MLXSW_SP_SB_TC_COUNT];
+		struct mlxsw_sp_sb_pm pms[2][MLXSW_SP_SB_POOL_COUNT];
+	} ports[MLXSW_PORT_MAX_PORTS];
+};
+
 struct mlxsw_sp {
 	struct {
 		struct list_head list;
@@ -129,6 +156,7 @@ struct mlxsw_sp {
 	struct mlxsw_sp_upper master_bridge;
 	struct mlxsw_sp_upper lags[MLXSW_SP_LAG_MAX];
 	u8 port_to_module[MLXSW_PORT_MAX_PORTS];
+	struct mlxsw_sp_sb sb;
 };
 
 static inline struct mlxsw_sp_upper *
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index 41212c0..beca792 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -40,14 +40,46 @@
 #include "port.h"
 #include "reg.h"
 
+static struct mlxsw_sp_sb_pr *mlxsw_sp_sb_pr_get(struct mlxsw_sp *mlxsw_sp,
+						 u8 pool,
+						 enum mlxsw_reg_sbxx_dir dir)
+{
+	return &mlxsw_sp->sb.prs[dir][pool];
+}
+
+static struct mlxsw_sp_sb_cm *mlxsw_sp_sb_cm_get(struct mlxsw_sp *mlxsw_sp,
+						 u8 local_port, u8 pg_buff,
+						 enum mlxsw_reg_sbxx_dir dir)
+{
+	return &mlxsw_sp->sb.ports[local_port].cms[dir][pg_buff];
+}
+
+static struct mlxsw_sp_sb_pm *mlxsw_sp_sb_pm_get(struct mlxsw_sp *mlxsw_sp,
+						 u8 local_port, u8 pool,
+						 enum mlxsw_reg_sbxx_dir dir)
+{
+	return &mlxsw_sp->sb.ports[local_port].pms[dir][pool];
+}
+
 static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u8 pool,
 				enum mlxsw_reg_sbxx_dir dir,
 				enum mlxsw_reg_sbpr_mode mode, u32 size)
 {
 	char sbpr_pl[MLXSW_REG_SBPR_LEN];
+	int err;
 
 	mlxsw_reg_sbpr_pack(sbpr_pl, pool, dir, mode, size);
-	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
+	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
+	if (err)
+		return err;
+	if (pool < MLXSW_SP_SB_POOL_COUNT) {
+		struct mlxsw_sp_sb_pr *pr;
+
+		pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
+		pr->mode = mode;
+		pr->size = size;
+	}
+	return 0;
 }
 
 static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
@@ -55,10 +87,22 @@ static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 				u32 min_buff, u32 max_buff, u8 pool)
 {
 	char sbcm_pl[MLXSW_REG_SBCM_LEN];
+	int err;
 
 	mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, dir,
 			    min_buff, max_buff, pool);
-	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
+	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
+	if (err)
+		return err;
+	if (pg_buff < MLXSW_SP_SB_TC_COUNT) {
+		struct mlxsw_sp_sb_cm *cm;
+
+		cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, pg_buff, dir);
+		cm->min_buff = min_buff;
+		cm->max_buff = max_buff;
+		cm->pool = pool;
+	}
+	return 0;
 }
 
 static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
@@ -66,9 +110,20 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 				u32 min_buff, u32 max_buff)
 {
 	char sbpm_pl[MLXSW_REG_SBPM_LEN];
+	int err;
 
 	mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, min_buff, max_buff);
-	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl);
+	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl);
+	if (err)
+		return err;
+	if (pool < MLXSW_SP_SB_POOL_COUNT) {
+		struct mlxsw_sp_sb_pm *pm;
+
+		pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool, dir);
+		pm->min_buff = min_buff;
+		pm->max_buff = max_buff;
+	}
+	return 0;
 }
 
 static const u16 mlxsw_sp_pbs[] = {
@@ -100,11 +155,6 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
 #define MLXSW_SP_SB_BYTES_PER_CELL 96
 
-struct mlxsw_sp_sb_pr {
-	enum mlxsw_reg_sbpr_mode mode;
-	u32 size;
-};
-
 #define MLXSW_SP_SB_PR_INGRESS_SIZE				\
 	((15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) /	\
 	 MLXSW_SP_SB_BYTES_PER_CELL)
@@ -174,12 +224,6 @@ static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp)
 					MLXSW_SP_SB_PRS_EGRESS_LEN);
 }
 
-struct mlxsw_sp_sb_cm {
-	u32 min_buff;
-	u32 max_buff;
-	u8 pool;
-};
-
 #define MLXSW_SP_SB_CM(_min_buff, _max_buff, _pool)	\
 	{						\
 		.min_buff = _min_buff,			\
@@ -312,11 +356,6 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
 				      MLXSW_SP_CPU_PORT_SB_MCS_LEN);
 }
 
-struct mlxsw_sp_sb_pm {
-	u32 min_buff;
-	u32 max_buff;
-};
-
 #define MLXSW_SP_SB_PM(_min_buff, _max_buff)	\
 	{					\
 		.min_buff = _min_buff,		\
@@ -442,8 +481,10 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
 	if (err)
 		return err;
 	err = mlxsw_sp_sb_mms_init(mlxsw_sp);
+	if (err)
+		return err;
 
-	return err;
+	return 0;
 }
 
 int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port)
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 11/13] mlxsw: spectrum_buffers: Rename "pool" to "pr" in initialization
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Be consintent with rest of the registers (pm, cm) and use "pr" here.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 70 +++++++++++-----------
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index 820a19c0..41212c0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -100,78 +100,78 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
 #define MLXSW_SP_SB_BYTES_PER_CELL 96
 
-struct mlxsw_sp_sb_pool {
+struct mlxsw_sp_sb_pr {
 	enum mlxsw_reg_sbpr_mode mode;
 	u32 size;
 };
 
-#define MLXSW_SP_SB_POOL_INGRESS_SIZE				\
+#define MLXSW_SP_SB_PR_INGRESS_SIZE				\
 	((15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) /	\
 	 MLXSW_SP_SB_BYTES_PER_CELL)
-#define MLXSW_SP_SB_POOL_EGRESS_SIZE				\
+#define MLXSW_SP_SB_PR_EGRESS_SIZE				\
 	((14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) /	\
 	 MLXSW_SP_SB_BYTES_PER_CELL)
 
-#define MLXSW_SP_SB_POOL(_mode, _size)	\
+#define MLXSW_SP_SB_PR(_mode, _size)	\
 	{				\
 		.mode = _mode,		\
 		.size = _size,		\
 	}
 
-static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_ingress[] = {
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC,
-			 MLXSW_SP_SB_POOL_INGRESS_SIZE),
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_ingress[] = {
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+		       MLXSW_SP_SB_PR_INGRESS_SIZE),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
 };
 
-#define MLXSW_SP_SB_POOLS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_ingress)
+#define MLXSW_SP_SB_PRS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_ingress)
 
-static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_egress[] = {
+static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_egress[] = {
 
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC,
-			 MLXSW_SP_SB_POOL_EGRESS_SIZE),
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
-	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC,
-			 MLXSW_SP_SB_POOL_EGRESS_SIZE),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+		       MLXSW_SP_SB_PR_EGRESS_SIZE),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
+		       MLXSW_SP_SB_PR_EGRESS_SIZE),
 };
 
-#define MLXSW_SP_SB_POOLS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_egress)
+#define MLXSW_SP_SB_PRS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_egress)
 
-static int __mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp,
-				    enum mlxsw_reg_sbxx_dir dir,
-				    const struct mlxsw_sp_sb_pool *pools,
-				    size_t pools_len)
+static int __mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp,
+				  enum mlxsw_reg_sbxx_dir dir,
+				  const struct mlxsw_sp_sb_pr *prs,
+				  size_t prs_len)
 {
 	int i;
 	int err;
 
-	for (i = 0; i < pools_len; i++) {
-		const struct mlxsw_sp_sb_pool *pool;
+	for (i = 0; i < prs_len; i++) {
+		const struct mlxsw_sp_sb_pr *pr;
 
-		pool = &pools[i];
+		pr = &prs[i];
 		err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, dir,
-					   pool->mode, pool->size);
+					   pr->mode, pr->size);
 		if (err)
 			return err;
 	}
 	return 0;
 }
 
-static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
+static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp)
 {
 	int err;
 
-	err = __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS,
-				       mlxsw_sp_sb_pools_ingress,
-				       MLXSW_SP_SB_POOLS_INGRESS_LEN);
+	err = __mlxsw_sp_sb_prs_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS,
+				     mlxsw_sp_sb_prs_ingress,
+				     MLXSW_SP_SB_PRS_INGRESS_LEN);
 	if (err)
 		return err;
-	return __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS,
-					mlxsw_sp_sb_pools_egress,
-					MLXSW_SP_SB_POOLS_EGRESS_LEN);
+	return __mlxsw_sp_sb_prs_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS,
+					mlxsw_sp_sb_prs_egress,
+					MLXSW_SP_SB_PRS_EGRESS_LEN);
 }
 
 struct mlxsw_sp_sb_cm {
@@ -435,7 +435,7 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
 {
 	int err;
 
-	err = mlxsw_sp_sb_pools_init(mlxsw_sp);
+	err = mlxsw_sp_sb_prs_init(mlxsw_sp);
 	if (err)
 		return err;
 	err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp);
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 10/13] mlxsw: spectrum_buffers: Push out indexes and direction out of SB structs
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Structs are in arrays so use array index as pool/tc/prio index. With
that, there is need to maintain separate assrys for ingress and egress.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 426 +++++++++++----------
 1 file changed, 220 insertions(+), 206 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index cc40f4c..820a19c0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -71,27 +71,16 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl);
 }
 
-struct mlxsw_sp_pb {
-	u8 index;
-	u16 size;
-};
-
-#define MLXSW_SP_PB(_index, _size)	\
-	{				\
-		.index = _index,	\
-		.size = _size,		\
-	}
-
-static const struct mlxsw_sp_pb mlxsw_sp_pbs[] = {
-	MLXSW_SP_PB(0, 208),
-	MLXSW_SP_PB(1, 208),
-	MLXSW_SP_PB(2, 208),
-	MLXSW_SP_PB(3, 208),
-	MLXSW_SP_PB(4, 208),
-	MLXSW_SP_PB(5, 208),
-	MLXSW_SP_PB(6, 208),
-	MLXSW_SP_PB(7, 208),
-	MLXSW_SP_PB(9, 208),
+static const u16 mlxsw_sp_pbs[] = {
+	208,
+	208,
+	208,
+	208,
+	208,
+	208,
+	208,
+	208,
+	208,
 };
 
 #define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs)
@@ -103,12 +92,8 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
 	mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port,
 			    0xffff, 0xffff / 2);
-	for (i = 0; i < MLXSW_SP_PBS_LEN; i++) {
-		const struct mlxsw_sp_pb *pb;
-
-		pb = &mlxsw_sp_pbs[i];
-		mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pb->index, pb->size);
-	}
+	for (i = 0; i < MLXSW_SP_PBS_LEN; i++)
+		mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, mlxsw_sp_pbs[i]);
 	return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core,
 			       MLXSW_REG(pbmc), pbmc_pl);
 }
@@ -116,8 +101,6 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 #define MLXSW_SP_SB_BYTES_PER_CELL 96
 
 struct mlxsw_sp_sb_pool {
-	u8 pool;
-	enum mlxsw_reg_sbxx_dir dir;
 	enum mlxsw_reg_sbpr_mode mode;
 	u32 size;
 };
@@ -129,45 +112,47 @@ struct mlxsw_sp_sb_pool {
 	((14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) /	\
 	 MLXSW_SP_SB_BYTES_PER_CELL)
 
-#define MLXSW_SP_SB_POOL(_pool, _dir, _mode, _size)		\
-	{							\
-		.pool = _pool,					\
-		.dir = _dir,					\
-		.mode = _mode,					\
-		.size = _size,					\
+#define MLXSW_SP_SB_POOL(_mode, _size)	\
+	{				\
+		.mode = _mode,		\
+		.size = _size,		\
 	}
 
-#define MLXSW_SP_SB_POOL_INGRESS(_pool, _size)			\
-	MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_INGRESS,	\
-			 MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
-
-#define MLXSW_SP_SB_POOL_EGRESS(_pool, _size)			\
-	MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_EGRESS,	\
-			 MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
-
-static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = {
-	MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_SB_POOL_INGRESS_SIZE),
-	MLXSW_SP_SB_POOL_INGRESS(1, 0),
-	MLXSW_SP_SB_POOL_INGRESS(2, 0),
-	MLXSW_SP_SB_POOL_INGRESS(3, 0),
-	MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_SB_POOL_EGRESS_SIZE),
-	MLXSW_SP_SB_POOL_EGRESS(1, 0),
-	MLXSW_SP_SB_POOL_EGRESS(2, 0),
-	MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_SB_POOL_EGRESS_SIZE),
+static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_ingress[] = {
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC,
+			 MLXSW_SP_SB_POOL_INGRESS_SIZE),
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
 };
 
-#define MLXSW_SP_SB_POOLS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools)
+#define MLXSW_SP_SB_POOLS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_ingress)
 
-static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
+static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools_egress[] = {
+
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC,
+			 MLXSW_SP_SB_POOL_EGRESS_SIZE),
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
+	MLXSW_SP_SB_POOL(MLXSW_REG_SBPR_MODE_DYNAMIC,
+			 MLXSW_SP_SB_POOL_EGRESS_SIZE),
+};
+
+#define MLXSW_SP_SB_POOLS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools_egress)
+
+static int __mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp,
+				    enum mlxsw_reg_sbxx_dir dir,
+				    const struct mlxsw_sp_sb_pool *pools,
+				    size_t pools_len)
 {
 	int i;
 	int err;
 
-	for (i = 0; i < MLXSW_SP_SB_POOLS_LEN; i++) {
+	for (i = 0; i < pools_len; i++) {
 		const struct mlxsw_sp_sb_pool *pool;
 
-		pool = &mlxsw_sp_sb_pools[i];
-		err = mlxsw_sp_sb_pr_write(mlxsw_sp, pool->pool, pool->dir,
+		pool = &pools[i];
+		err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, dir,
 					   pool->mode, pool->size);
 		if (err)
 			return err;
@@ -175,109 +160,114 @@ static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
 	return 0;
 }
 
+static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp)
+{
+	int err;
+
+	err = __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS,
+				       mlxsw_sp_sb_pools_ingress,
+				       MLXSW_SP_SB_POOLS_INGRESS_LEN);
+	if (err)
+		return err;
+	return __mlxsw_sp_sb_pools_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS,
+					mlxsw_sp_sb_pools_egress,
+					MLXSW_SP_SB_POOLS_EGRESS_LEN);
+}
+
 struct mlxsw_sp_sb_cm {
-	union {
-		u8 pg;
-		u8 tc;
-	} u;
-	enum mlxsw_reg_sbxx_dir dir;
 	u32 min_buff;
 	u32 max_buff;
 	u8 pool;
 };
 
-#define MLXSW_SP_SB_CM(_pg_tc, _dir, _min_buff, _max_buff, _pool)	\
-	{								\
-		.u.pg = _pg_tc,						\
-		.dir = _dir,						\
-		.min_buff = _min_buff,					\
-		.max_buff = _max_buff,					\
-		.pool = _pool,						\
+#define MLXSW_SP_SB_CM(_min_buff, _max_buff, _pool)	\
+	{						\
+		.min_buff = _min_buff,			\
+		.max_buff = _max_buff,			\
+		.pool = _pool,				\
 	}
 
-#define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff)		\
-	MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBXX_DIR_INGRESS,			\
-		       _min_buff, _max_buff, 0)
-
-#define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff)		\
-	MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS,			\
-		       _min_buff, _max_buff, 0)
-
-#define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc)				\
-	MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS, 104, 2, 3)
-
-static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = {
-	MLXSW_SP_SB_CM_INGRESS(0, 10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8),
-	MLXSW_SP_SB_CM_INGRESS(1, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(2, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(3, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(4, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(5, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(6, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(7, 0, 0),
-	MLXSW_SP_SB_CM_INGRESS(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff),
-	MLXSW_SP_SB_CM_EGRESS(0, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(1, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(2, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(3, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(4, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(5, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(6, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(7, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9),
-	MLXSW_SP_SB_CM_EGRESS(8, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(9, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(10, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(11, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(12, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(13, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(14, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(15, 0, 0),
-	MLXSW_SP_SB_CM_EGRESS(16, 1, 0xff),
+static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = {
+	MLXSW_SP_SB_CM(10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */
+	MLXSW_SP_SB_CM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+};
+
+#define MLXSW_SP_SB_CMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_ingress)
+
+static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = {
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(0, 0, 0),
+	MLXSW_SP_SB_CM(1, 0xff, 0),
 };
 
-#define MLXSW_SP_SB_CMS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms)
+#define MLXSW_SP_SB_CMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_egress)
+
+#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(104, 2, 3)
 
 static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = {
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(0),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(1),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(2),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(3),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(4),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(5),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(6),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(7),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(8),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(9),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(10),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(11),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(12),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(13),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(14),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(15),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(16),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(17),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(18),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(19),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(20),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(21),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(22),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(23),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(24),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(25),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(26),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(27),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(28),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(29),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(30),
-	MLXSW_SP_CPU_PORT_SB_CM_EGRESS(31),
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
+	MLXSW_SP_CPU_PORT_SB_CM,
 };
 
 #define MLXSW_SP_CPU_PORT_SB_MCS_LEN \
 	ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms)
 
-static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-				const struct mlxsw_sp_sb_cm *cms,
-				size_t cms_len)
+static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+				  enum mlxsw_reg_sbxx_dir dir,
+				  const struct mlxsw_sp_sb_cm *cms,
+				  size_t cms_len)
 {
 	int i;
 	int err;
@@ -285,10 +275,12 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 	for (i = 0; i < cms_len; i++) {
 		const struct mlxsw_sp_sb_cm *cm;
 
+		if (i == 8 && dir == MLXSW_REG_SBXX_DIR_INGRESS)
+			continue; /* PG number 8 does not exist, skip it */
 		cm = &cms[i];
-		err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, cm->u.pg,
-					   cm->dir, cm->min_buff,
-					   cm->max_buff, cm->pool);
+		err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, i, dir,
+					   cm->min_buff, cm->max_buff,
+					   cm->pool);
 		if (err)
 			return err;
 	}
@@ -297,65 +289,71 @@ static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 
 static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port)
 {
-	return mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
-				    mlxsw_sp_port->local_port, mlxsw_sp_sb_cms,
-				    MLXSW_SP_SB_CMS_LEN);
+	int err;
+
+	err = __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
+				     mlxsw_sp_port->local_port,
+				     MLXSW_REG_SBXX_DIR_INGRESS,
+				     mlxsw_sp_sb_cms_ingress,
+				     MLXSW_SP_SB_CMS_INGRESS_LEN);
+	if (err)
+		return err;
+	return __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
+				      mlxsw_sp_port->local_port,
+				      MLXSW_REG_SBXX_DIR_EGRESS,
+				      mlxsw_sp_sb_cms_egress,
+				      MLXSW_SP_SB_CMS_EGRESS_LEN);
 }
 
 static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
 {
-	return mlxsw_sp_sb_cms_init(mlxsw_sp, 0, mlxsw_sp_cpu_port_sb_cms,
-				    MLXSW_SP_CPU_PORT_SB_MCS_LEN);
+	return __mlxsw_sp_sb_cms_init(mlxsw_sp, 0, MLXSW_REG_SBXX_DIR_EGRESS,
+				      mlxsw_sp_cpu_port_sb_cms,
+				      MLXSW_SP_CPU_PORT_SB_MCS_LEN);
 }
 
 struct mlxsw_sp_sb_pm {
-	u8 pool;
-	enum mlxsw_reg_sbxx_dir dir;
 	u32 min_buff;
 	u32 max_buff;
 };
 
-#define MLXSW_SP_SB_PM(_pool, _dir, _min_buff, _max_buff)	\
-	{							\
-		.pool = _pool,					\
-		.dir = _dir,					\
-		.min_buff = _min_buff,				\
-		.max_buff = _max_buff,				\
+#define MLXSW_SP_SB_PM(_min_buff, _max_buff)	\
+	{					\
+		.min_buff = _min_buff,		\
+		.max_buff = _max_buff,		\
 	}
 
-#define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff)	\
-	MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_INGRESS,	\
-		       _min_buff, _max_buff)
-
-#define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff)	\
-	MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_EGRESS,	\
-		       _min_buff, _max_buff)
-
-static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
-	MLXSW_SP_SB_PM_INGRESS(0, 0, 0xff),
-	MLXSW_SP_SB_PM_INGRESS(1, 0, 0),
-	MLXSW_SP_SB_PM_INGRESS(2, 0, 0),
-	MLXSW_SP_SB_PM_INGRESS(3, 0, 0),
-	MLXSW_SP_SB_PM_EGRESS(0, 0, 7),
-	MLXSW_SP_SB_PM_EGRESS(1, 0, 0),
-	MLXSW_SP_SB_PM_EGRESS(2, 0, 0),
-	MLXSW_SP_SB_PM_EGRESS(3, 0, 0),
+static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_ingress[] = {
+	MLXSW_SP_SB_PM(0, 0xff),
+	MLXSW_SP_SB_PM(0, 0),
+	MLXSW_SP_SB_PM(0, 0),
+	MLXSW_SP_SB_PM(0, 0),
 };
 
-#define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms)
+#define MLXSW_SP_SB_PMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_ingress)
 
-static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
+static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_egress[] = {
+	MLXSW_SP_SB_PM(0, 7),
+	MLXSW_SP_SB_PM(0, 0),
+	MLXSW_SP_SB_PM(0, 0),
+	MLXSW_SP_SB_PM(0, 0),
+};
+
+#define MLXSW_SP_SB_PMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_egress)
+
+static int __mlxsw_sp_port_sb_pms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+				       enum mlxsw_reg_sbxx_dir dir,
+				       const struct mlxsw_sp_sb_pm *pms,
+				       size_t pms_len)
 {
 	int i;
 	int err;
 
-	for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) {
+	for (i = 0; i < pms_len; i++) {
 		const struct mlxsw_sp_sb_pm *pm;
 
-		pm = &mlxsw_sp_sb_pms[i];
-		err = mlxsw_sp_sb_pm_write(mlxsw_sp_port->mlxsw_sp,
-					   mlxsw_sp_port->local_port,
-					   pm->pool, pm->dir,
+		pm = &pms[i];
+		err = mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, i, dir,
 					   pm->min_buff, pm->max_buff);
 		if (err)
 			return err;
@@ -363,37 +361,53 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
 	return 0;
 }
 
+static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+	int err;
+
+	err = __mlxsw_sp_port_sb_pms_init(mlxsw_sp_port->mlxsw_sp,
+					  mlxsw_sp_port->local_port,
+					  MLXSW_REG_SBXX_DIR_INGRESS,
+					  mlxsw_sp_sb_pms_ingress,
+					  MLXSW_SP_SB_PMS_INGRESS_LEN);
+	if (err)
+		return err;
+	return __mlxsw_sp_port_sb_pms_init(mlxsw_sp_port->mlxsw_sp,
+					   mlxsw_sp_port->local_port,
+					   MLXSW_REG_SBXX_DIR_EGRESS,
+					   mlxsw_sp_sb_pms_egress,
+					   MLXSW_SP_SB_PMS_EGRESS_LEN);
+}
+
 struct mlxsw_sp_sb_mm {
-	u8 prio;
 	u32 min_buff;
 	u32 max_buff;
 	u8 pool;
 };
 
-#define MLXSW_SP_SB_MM(_prio, _min_buff, _max_buff, _pool)	\
-	{							\
-		.prio = _prio,					\
-		.min_buff = _min_buff,				\
-		.max_buff = _max_buff,				\
-		.pool = _pool,					\
+#define MLXSW_SP_SB_MM(_min_buff, _max_buff, _pool)	\
+	{						\
+		.min_buff = _min_buff,			\
+		.max_buff = _max_buff,			\
+		.pool = _pool,				\
 	}
 
 static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = {
-	MLXSW_SP_SB_MM(0, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(1, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(2, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(3, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(4, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(5, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(6, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(7, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(8, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(10, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(11, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(12, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(13, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
-	MLXSW_SP_SB_MM(14, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
+	MLXSW_SP_SB_MM(20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0),
 };
 
 #define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms)
@@ -408,7 +422,7 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp)
 		const struct mlxsw_sp_sb_mm *mc;
 
 		mc = &mlxsw_sp_sb_mms[i];
-		mlxsw_reg_sbmm_pack(sbmm_pl, mc->prio, mc->min_buff,
+		mlxsw_reg_sbmm_pack(sbmm_pl, i, mc->min_buff,
 				    mc->max_buff, mc->pool);
 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl);
 		if (err)
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 08/13] mlxsw: core: Add devlink shared buffer callbacks
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Add middle layer in mlxsw core code to forward shared buffer calls
into specific ASIC drivers.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.c | 105 ++++++++++++++++++++++++++++-
 drivers/net/ethernet/mellanox/mlxsw/core.h |  20 ++++++
 2 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 3958195..1278260 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -816,9 +816,110 @@ static int mlxsw_devlink_port_unsplit(struct devlink *devlink,
 	return mlxsw_core->driver->port_unsplit(mlxsw_core, port_index);
 }
 
+static int
+mlxsw_devlink_sb_pool_get(struct devlink *devlink,
+			  unsigned int sb_index, u16 pool_index,
+			  struct devlink_sb_pool_info *pool_info)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->sb_pool_get)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->sb_pool_get(mlxsw_core, sb_index,
+					 pool_index, pool_info);
+}
+
+static int
+mlxsw_devlink_sb_pool_set(struct devlink *devlink,
+			  unsigned int sb_index, u16 pool_index, u32 size,
+			  enum devlink_sb_threshold_type threshold_type)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+
+	if (!mlxsw_driver->sb_pool_set)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->sb_pool_set(mlxsw_core, sb_index,
+					 pool_index, size, threshold_type);
+}
+
+static void *__dl_port(struct devlink_port *devlink_port)
+{
+	return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
+}
+
+static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
+					  unsigned int sb_index, u16 pool_index,
+					  u32 *p_threshold)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
+
+	if (!mlxsw_driver->sb_port_pool_get)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index,
+					      pool_index, p_threshold);
+}
+
+static int mlxsw_devlink_sb_port_pool_set(struct devlink_port *devlink_port,
+					  unsigned int sb_index, u16 pool_index,
+					  u32 threshold)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
+
+	if (!mlxsw_driver->sb_port_pool_set)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index,
+					      pool_index, threshold);
+}
+
+static int
+mlxsw_devlink_sb_tc_pool_bind_get(struct devlink_port *devlink_port,
+				  unsigned int sb_index, u16 tc_index,
+				  enum devlink_sb_pool_type pool_type,
+				  u16 *p_pool_index, u32 *p_threshold)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
+
+	if (!mlxsw_driver->sb_tc_pool_bind_get)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index,
+						 tc_index, pool_type,
+						 p_pool_index, p_threshold);
+}
+
+static int
+mlxsw_devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
+				  unsigned int sb_index, u16 tc_index,
+				  enum devlink_sb_pool_type pool_type,
+				  u16 pool_index, u32 threshold)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
+
+	if (!mlxsw_driver->sb_tc_pool_bind_set)
+		return -EOPNOTSUPP;
+	return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index,
+						 tc_index, pool_type,
+						 pool_index, threshold);
+}
+
 static const struct devlink_ops mlxsw_devlink_ops = {
-	.port_split	= mlxsw_devlink_port_split,
-	.port_unsplit	= mlxsw_devlink_port_unsplit,
+	.port_split		= mlxsw_devlink_port_split,
+	.port_unsplit		= mlxsw_devlink_port_unsplit,
+	.sb_pool_get		= mlxsw_devlink_sb_pool_get,
+	.sb_pool_set		= mlxsw_devlink_sb_pool_set,
+	.sb_port_pool_get	= mlxsw_devlink_sb_port_pool_get,
+	.sb_port_pool_set	= mlxsw_devlink_sb_port_pool_set,
+	.sb_tc_pool_bind_get	= mlxsw_devlink_sb_tc_pool_bind_get,
+	.sb_tc_pool_bind_set	= mlxsw_devlink_sb_tc_pool_bind_set,
 };
 
 int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 85ded38..2ba72e1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -209,6 +209,26 @@ struct mlxsw_driver {
 	int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port,
 			  unsigned int count);
 	int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port);
+	int (*sb_pool_get)(struct mlxsw_core *mlxsw_core,
+			   unsigned int sb_index, u16 pool_index,
+			   struct devlink_sb_pool_info *pool_info);
+	int (*sb_pool_set)(struct mlxsw_core *mlxsw_core,
+			   unsigned int sb_index, u16 pool_index, u32 size,
+			   enum devlink_sb_threshold_type threshold_type);
+	int (*sb_port_pool_get)(struct mlxsw_core_port *mlxsw_core_port,
+				unsigned int sb_index, u16 pool_index,
+				u32 *p_threshold);
+	int (*sb_port_pool_set)(struct mlxsw_core_port *mlxsw_core_port,
+				unsigned int sb_index,u16 pool_index,
+				u32 threshold);
+	int (*sb_tc_pool_bind_get)(struct mlxsw_core_port *mlxsw_core_port,
+				   unsigned int sb_index, u16 tc_index,
+				   enum devlink_sb_pool_type pool_type,
+				   u16 *p_pool_index, u32 *p_threshold);
+	int (*sb_tc_pool_bind_set)(struct mlxsw_core_port *mlxsw_core_port,
+				   unsigned int sb_index, u16 tc_index,
+				   enum devlink_sb_pool_type pool_type,
+				   u16 pool_index, u32 threshold);
 	void (*txhdr_construct)(struct sk_buff *skb,
 				const struct mlxsw_tx_info *tx_info);
 	u8 txhdr_len;
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 06/13] mlxsw: reg: Share direction enum between SBPR, SBCM, SBPM
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Same field, same values, so share the same enum.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h          | 23 +++++++---------------
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 20 +++++++++----------
 2 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index ffe4c03..fa1c7bd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -2985,9 +2985,10 @@ static const struct mlxsw_reg_info mlxsw_reg_sbpr = {
 	.len = MLXSW_REG_SBPR_LEN,
 };
 
-enum mlxsw_reg_sbpr_dir {
-	MLXSW_REG_SBPR_DIR_INGRESS,
-	MLXSW_REG_SBPR_DIR_EGRESS,
+/* shared direstion enum for SBPR, SBCM, SBPM */
+enum mlxsw_reg_sbxx_dir {
+	MLXSW_REG_SBXX_DIR_INGRESS,
+	MLXSW_REG_SBXX_DIR_EGRESS,
 };
 
 /* reg_sbpr_dir
@@ -3020,7 +3021,7 @@ enum mlxsw_reg_sbpr_mode {
 MLXSW_ITEM32(reg, sbpr, mode, 0x08, 0, 4);
 
 static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool,
-				       enum mlxsw_reg_sbpr_dir dir,
+				       enum mlxsw_reg_sbxx_dir dir,
 				       enum mlxsw_reg_sbpr_mode mode, u32 size)
 {
 	MLXSW_REG_ZERO(sbpr, payload);
@@ -3062,11 +3063,6 @@ MLXSW_ITEM32(reg, sbcm, local_port, 0x00, 16, 8);
  */
 MLXSW_ITEM32(reg, sbcm, pg_buff, 0x00, 8, 6);
 
-enum mlxsw_reg_sbcm_dir {
-	MLXSW_REG_SBCM_DIR_INGRESS,
-	MLXSW_REG_SBCM_DIR_EGRESS,
-};
-
 /* reg_sbcm_dir
  * Direction.
  * Access: Index
@@ -3099,7 +3095,7 @@ MLXSW_ITEM32(reg, sbcm, max_buff, 0x1C, 0, 24);
 MLXSW_ITEM32(reg, sbcm, pool, 0x24, 0, 4);
 
 static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff,
-				       enum mlxsw_reg_sbcm_dir dir,
+				       enum mlxsw_reg_sbxx_dir dir,
 				       u32 min_buff, u32 max_buff, u8 pool)
 {
 	MLXSW_REG_ZERO(sbcm, payload);
@@ -3139,11 +3135,6 @@ MLXSW_ITEM32(reg, sbpm, local_port, 0x00, 16, 8);
  */
 MLXSW_ITEM32(reg, sbpm, pool, 0x00, 8, 4);
 
-enum mlxsw_reg_sbpm_dir {
-	MLXSW_REG_SBPM_DIR_INGRESS,
-	MLXSW_REG_SBPM_DIR_EGRESS,
-};
-
 /* reg_sbpm_dir
  * Direction.
  * Access: Index
@@ -3170,7 +3161,7 @@ MLXSW_ITEM32(reg, sbpm, min_buff, 0x18, 0, 24);
 MLXSW_ITEM32(reg, sbpm, max_buff, 0x1C, 0, 24);
 
 static inline void mlxsw_reg_sbpm_pack(char *payload, u8 local_port, u8 pool,
-				       enum mlxsw_reg_sbpm_dir dir,
+				       enum mlxsw_reg_sbxx_dir dir,
 				       u32 min_buff, u32 max_buff)
 {
 	MLXSW_REG_ZERO(sbpm, payload);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
index d59195e..fb5f787 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
@@ -86,7 +86,7 @@ static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
 
 struct mlxsw_sp_sb_pool {
 	u8 pool;
-	enum mlxsw_reg_sbpr_dir dir;
+	enum mlxsw_reg_sbxx_dir dir;
 	enum mlxsw_reg_sbpr_mode mode;
 	u32 size;
 };
@@ -107,11 +107,11 @@ struct mlxsw_sp_sb_pool {
 	}
 
 #define MLXSW_SP_SB_POOL_INGRESS(_pool, _size)			\
-	MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_INGRESS,	\
+	MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_INGRESS,	\
 			 MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
 
 #define MLXSW_SP_SB_POOL_EGRESS(_pool, _size)			\
-	MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_EGRESS,	\
+	MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBXX_DIR_EGRESS,	\
 			 MLXSW_REG_SBPR_MODE_DYNAMIC, _size)
 
 static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = {
@@ -151,7 +151,7 @@ struct mlxsw_sp_sb_cm {
 		u8 pg;
 		u8 tc;
 	} u;
-	enum mlxsw_reg_sbcm_dir dir;
+	enum mlxsw_reg_sbxx_dir dir;
 	u32 min_buff;
 	u32 max_buff;
 	u8 pool;
@@ -167,15 +167,15 @@ struct mlxsw_sp_sb_cm {
 	}
 
 #define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff)		\
-	MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBCM_DIR_INGRESS,			\
+	MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBXX_DIR_INGRESS,			\
 		       _min_buff, _max_buff, 0)
 
 #define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff)		\
-	MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS,			\
+	MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS,			\
 		       _min_buff, _max_buff, 0)
 
 #define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc)				\
-	MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, 104, 2, 3)
+	MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBXX_DIR_EGRESS, 104, 2, 3)
 
 static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = {
 	MLXSW_SP_SB_CM_INGRESS(0, 10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8),
@@ -282,7 +282,7 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
 
 struct mlxsw_sp_sb_pm {
 	u8 pool;
-	enum mlxsw_reg_sbpm_dir dir;
+	enum mlxsw_reg_sbxx_dir dir;
 	u32 min_buff;
 	u32 max_buff;
 };
@@ -296,11 +296,11 @@ struct mlxsw_sp_sb_pm {
 	}
 
 #define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff)	\
-	MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_INGRESS,	\
+	MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_INGRESS,	\
 		       _min_buff, _max_buff)
 
 #define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff)	\
-	MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_EGRESS,	\
+	MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBXX_DIR_EGRESS,	\
 		       _min_buff, _max_buff)
 
 static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = {
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 07/13] mlxsw: reg: Fix SBPM register name
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Fix copy&paste error and state the name of SBPM register correctly.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index fa1c7bd..41186cc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -3107,8 +3107,8 @@ static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff,
 	mlxsw_reg_sbcm_pool_set(payload, pool);
 }
 
-/* SBPM - Shared Buffer Class Management Register
- * ----------------------------------------------
+/* SBPM - Shared Buffer Port Management Register
+ * ---------------------------------------------
  * The SBPM register configures and retrieves the shared buffer allocation
  * and configuration according to Port-Pool, including the definition
  * of the associated quota.
-- 
2.5.0

^ permalink raw reply related

* [patch net-next RFC 04/13] mlxsw: Pass mlxsw_core as a param of mlxsw_core_skb_transmit*
From: Jiri Pirko @ 2016-03-17 17:13 UTC (permalink / raw)
  To: netdev
  Cc: davem, idosch, eladr, yotamg, ogerlitz, roopa, nikolay, jhs,
	john.fastabend, rami.rosen, gospo, stephen, sfeldma
In-Reply-To: <1458234833-25836-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Instead of passing around driver priv, pass struct mlxsw_core *
directly.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/core.c     | 15 +++------------
 drivers/net/ethernet/mellanox/mlxsw/core.h     |  5 ++---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c |  4 ++--
 drivers/net/ethernet/mellanox/mlxsw/switchx2.c |  4 ++--
 4 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 004fb8b..39161fb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -381,7 +381,7 @@ static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
 
 	mlxsw_core->emad.trans_active = true;
 
-	err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info);
+	err = mlxsw_core_skb_transmit(mlxsw_core, skb, tx_info);
 	if (err) {
 		dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n",
 			mlxsw_core->emad.tid);
@@ -929,26 +929,17 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
 }
 EXPORT_SYMBOL(mlxsw_core_bus_device_unregister);
 
-static struct mlxsw_core *__mlxsw_core_get(void *driver_priv)
-{
-	return container_of(driver_priv, struct mlxsw_core, driver_priv);
-}
-
-bool mlxsw_core_skb_transmit_busy(void *driver_priv,
+bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core,
 				  const struct mlxsw_tx_info *tx_info)
 {
-	struct mlxsw_core *mlxsw_core = __mlxsw_core_get(driver_priv);
-
 	return mlxsw_core->bus->skb_transmit_busy(mlxsw_core->bus_priv,
 						  tx_info);
 }
 EXPORT_SYMBOL(mlxsw_core_skb_transmit_busy);
 
-int mlxsw_core_skb_transmit(void *driver_priv, struct sk_buff *skb,
+int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
 			    const struct mlxsw_tx_info *tx_info)
 {
-	struct mlxsw_core *mlxsw_core = __mlxsw_core_get(driver_priv);
-
 	return mlxsw_core->bus->skb_transmit(mlxsw_core->bus_priv, skb,
 					     tx_info);
 }
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index cc8fceb..f8054a7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -75,10 +75,9 @@ struct mlxsw_tx_info {
 	bool is_emad;
 };
 
-bool mlxsw_core_skb_transmit_busy(void *driver_priv,
+bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core,
 				  const struct mlxsw_tx_info *tx_info);
-
-int mlxsw_core_skb_transmit(void *driver_priv, struct sk_buff *skb,
+int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
 			    const struct mlxsw_tx_info *tx_info);
 
 struct mlxsw_rx_listener {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 22bba32..1e4dc5e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -378,7 +378,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
 	u64 len;
 	int err;
 
-	if (mlxsw_core_skb_transmit_busy(mlxsw_sp, &tx_info))
+	if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info))
 		return NETDEV_TX_BUSY;
 
 	if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
@@ -402,7 +402,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
 	/* Due to a race we might fail here because of a full queue. In that
 	 * unlikely case we simply drop the packet.
 	 */
-	err = mlxsw_core_skb_transmit(mlxsw_sp, skb, &tx_info);
+	err = mlxsw_core_skb_transmit(mlxsw_sp->core, skb, &tx_info);
 
 	if (!err) {
 		pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index f4f2a9d..087c094 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -302,7 +302,7 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
 	u64 len;
 	int err;
 
-	if (mlxsw_core_skb_transmit_busy(mlxsw_sx, &tx_info))
+	if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info))
 		return NETDEV_TX_BUSY;
 
 	if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
@@ -320,7 +320,7 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
 	/* Due to a race we might fail here because of a full queue. In that
 	 * unlikely case we simply drop the packet.
 	 */
-	err = mlxsw_core_skb_transmit(mlxsw_sx, skb, &tx_info);
+	err = mlxsw_core_skb_transmit(mlxsw_sx->core, skb, &tx_info);
 
 	if (!err) {
 		pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats);
-- 
2.5.0

^ 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