netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/5] nfp: control processor DMA support and RJ45
@ 2019-02-27  4:19 Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 1/5] nfp: report RJ45 connector in ethtool Jakub Kicinski
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Jakub Kicinski @ 2019-02-27  4:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski

Hi!

This series starts with adding support for reporting twisted pair
media type in ethtool.

Remaining patches add support for using DMA with the control/service
processor.  Currently we always copy the command data into card's
memory.  DMA support allows us to have the NSP read the data from
host memory by itself.  Unfortunately, the FW loading and flashing
cannot directly map the buffers for DMA because (a) the firmware
ABI returns const buffers, and (b) the buffers may be vmalloc()ed
in many mysterious/unmappable way.  So just bite the bullet -
allocate new host buffer for the command and copy.

As Dirk explains, the NSP now supports updating all FWs at once
which means the max flashing time grew significantly.  He bumps
the max wait to avoid timeouts.

Dirk van der Merwe (1):
  nfp: nsp: set higher timeout for flash bundle

Jakub Kicinski (4):
  nfp: report RJ45 connector in ethtool
  nfp: nsp: use fractional size of the buffer
  nfp: nsp: move default buffer handling into its own function
  nfp: nsp: allow the use of DMA buffer

 .../ethernet/netronome/nfp/nfpcore/nfp_nsp.c  | 285 +++++++++++++++---
 .../ethernet/netronome/nfp/nfpcore/nfp_nsp.h  |   1 +
 .../netronome/nfp/nfpcore/nfp_nsp_eth.c       |   3 +
 3 files changed, 243 insertions(+), 46 deletions(-)

-- 
2.19.2


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

* [PATCH net-next 1/5] nfp: report RJ45 connector in ethtool
  2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
@ 2019-02-27  4:19 ` Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 2/5] nfp: nsp: use fractional size of the buffer Jakub Kicinski
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2019-02-27  4:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski

Add support for reporting twisted pair port type.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h     | 1 +
 drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
index 246e213f1514..bd9c358c646f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
@@ -49,6 +49,7 @@ enum nfp_eth_interface {
 	NFP_INTERFACE_SFPP	= 10,
 	NFP_INTERFACE_SFP28	= 28,
 	NFP_INTERFACE_QSFP	= 40,
+	NFP_INTERFACE_RJ45	= 45,
 	NFP_INTERFACE_CXP	= 100,
 	NFP_INTERFACE_QSFP28	= 112,
 };
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
index f6f028fa5db9..311a5be25acb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
@@ -206,6 +206,9 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry)
 	if (entry->interface == NFP_INTERFACE_NONE) {
 		entry->port_type = PORT_NONE;
 		return;
+	} else if (entry->interface == NFP_INTERFACE_RJ45) {
+		entry->port_type = PORT_TP;
+		return;
 	}
 
 	if (entry->media == NFP_MEDIA_FIBRE)
-- 
2.19.2


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

* [PATCH net-next 2/5] nfp: nsp: use fractional size of the buffer
  2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 1/5] nfp: report RJ45 connector in ethtool Jakub Kicinski
@ 2019-02-27  4:19 ` Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 3/5] nfp: nsp: move default buffer handling into its own function Jakub Kicinski
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2019-02-27  4:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski

NSP expresses the buffer size in MB and 4 kB blocks.  For small
buffers the kB part may make a difference, so count it in.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
---
 .../net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c    | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
index a9d53df0070c..22208b03ff49 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
@@ -49,6 +49,7 @@
 #define   NSP_DFLT_BUFFER_ADDRESS	GENMASK_ULL(39, 0)
 
 #define NSP_DFLT_BUFFER_CONFIG	0x20
+#define   NSP_DFLT_BUFFER_SIZE_4KB	GENMASK_ULL(15, 8)
 #define   NSP_DFLT_BUFFER_SIZE_MB	GENMASK_ULL(7, 0)
 
 #define NSP_MAGIC		0xab10
@@ -413,8 +414,8 @@ static int nfp_nsp_command(struct nfp_nsp *state, u16 code)
 static int
 nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
 {
+	unsigned int def_size, max_size;
 	struct nfp_cpp *cpp = nsp->cpp;
-	unsigned int max_size;
 	u64 reg, cpp_buf;
 	int ret, err;
 	u32 cpp_id;
@@ -433,11 +434,11 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
 		return err;
 
 	max_size = max(arg->in_size, arg->out_size);
-	if (FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M < max_size) {
-		nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%llu < %u)\n",
-			arg->arg.code,
-			FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M,
-			max_size);
+	def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
+		   FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
+	if (def_size < max_size) {
+		nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
+			arg->arg.code, def_size, max_size);
 		return -EINVAL;
 	}
 
-- 
2.19.2


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

* [PATCH net-next 3/5] nfp: nsp: move default buffer handling into its own function
  2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 1/5] nfp: report RJ45 connector in ethtool Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 2/5] nfp: nsp: use fractional size of the buffer Jakub Kicinski
@ 2019-02-27  4:19 ` Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 4/5] nfp: nsp: allow the use of DMA buffer Jakub Kicinski
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2019-02-27  4:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski

DMA version of NSP communication is coming, move the code which
copies data into the NFP buffer into a separate function.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
---
 .../ethernet/netronome/nfp/nfpcore/nfp_nsp.c  | 93 ++++++++++---------
 1 file changed, 51 insertions(+), 42 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
index 22208b03ff49..28262b0fc89a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
@@ -122,16 +122,14 @@ struct nfp_nsp {
  * @code:	NFP SP Command Code
  * @timeout_sec:Timeout value to wait for completion in seconds
  * @option:	NFP SP Command Argument
- * @buff_cpp:	NFP SP Buffer CPP Address info
- * @buff_addr:	NFP SP Buffer Host address
+ * @buf:	NFP SP Buffer Address
  * @error_cb:	Callback for interpreting option if error occurred
  */
 struct nfp_nsp_command_arg {
 	u16 code;
 	unsigned int timeout_sec;
 	u32 option;
-	u32 buff_cpp;
-	u64 buff_addr;
+	u64 buf;
 	void (*error_cb)(struct nfp_nsp *state, u32 ret_val);
 };
 
@@ -345,16 +343,7 @@ __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
 	if (err)
 		return err;
 
-	if (!FIELD_FIT(NSP_BUFFER_CPP, arg->buff_cpp >> 8) ||
-	    !FIELD_FIT(NSP_BUFFER_ADDRESS, arg->buff_addr)) {
-		nfp_err(cpp, "Host buffer out of reach %08x %016llx\n",
-			arg->buff_cpp, arg->buff_addr);
-		return -EINVAL;
-	}
-
-	err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer,
-			     FIELD_PREP(NSP_BUFFER_CPP, arg->buff_cpp >> 8) |
-			     FIELD_PREP(NSP_BUFFER_ADDRESS, arg->buff_addr));
+	err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf);
 	if (err < 0)
 		return err;
 
@@ -412,36 +401,14 @@ static int nfp_nsp_command(struct nfp_nsp *state, u16 code)
 }
 
 static int
-nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
+nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
+			struct nfp_nsp_command_buf_arg *arg)
 {
-	unsigned int def_size, max_size;
 	struct nfp_cpp *cpp = nsp->cpp;
 	u64 reg, cpp_buf;
-	int ret, err;
+	int err, ret;
 	u32 cpp_id;
 
-	if (nsp->ver.minor < 13) {
-		nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
-			arg->arg.code, nsp->ver.major, nsp->ver.minor);
-		return -EOPNOTSUPP;
-	}
-
-	err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
-			    nfp_resource_address(nsp->res) +
-			    NSP_DFLT_BUFFER_CONFIG,
-			    &reg);
-	if (err < 0)
-		return err;
-
-	max_size = max(arg->in_size, arg->out_size);
-	def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
-		   FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
-	if (def_size < max_size) {
-		nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
-			arg->arg.code, def_size, max_size);
-		return -EINVAL;
-	}
-
 	err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
 			    nfp_resource_address(nsp->res) +
 			    NSP_DFLT_BUFFER,
@@ -460,15 +427,21 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
 	}
 	/* Zero out remaining part of the buffer */
 	if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) {
-		memset(arg->out_buf, 0, arg->out_size - arg->in_size);
 		err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size,
 				    arg->out_buf, arg->out_size - arg->in_size);
 		if (err < 0)
 			return err;
 	}
 
-	arg->arg.buff_cpp = cpp_id;
-	arg->arg.buff_addr = cpp_buf;
+	if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) ||
+	    !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) {
+		nfp_err(cpp, "Buffer out of reach %08x %016llx\n",
+			cpp_id, cpp_buf);
+		return -EINVAL;
+	}
+
+	arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) |
+		       FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf);
 	ret = __nfp_nsp_command(nsp, &arg->arg);
 	if (ret < 0)
 		return ret;
@@ -483,6 +456,42 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
 	return ret;
 }
 
+static int
+nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
+{
+	unsigned int def_size, max_size;
+	struct nfp_cpp *cpp = nsp->cpp;
+	u64 reg;
+	int err;
+
+	if (nsp->ver.minor < 13) {
+		nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
+			arg->arg.code, nsp->ver.major, nsp->ver.minor);
+		return -EOPNOTSUPP;
+	}
+
+	err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
+			    nfp_resource_address(nsp->res) +
+			    NSP_DFLT_BUFFER_CONFIG,
+			    &reg);
+	if (err < 0)
+		return err;
+
+	/* Zero out undefined part of the out buffer */
+	if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size)
+		memset(arg->out_buf, 0, arg->out_size - arg->in_size);
+
+	max_size = max(arg->in_size, arg->out_size);
+	def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
+		   FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
+	if (def_size >= max_size)
+		return nfp_nsp_command_buf_def(nsp, arg);
+
+	nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
+		arg->arg.code, def_size, max_size);
+	return -EINVAL;
+}
+
 int nfp_nsp_wait(struct nfp_nsp *state)
 {
 	const unsigned long wait_until = jiffies + NFP_NSP_TIMEOUT_BOOT * HZ;
-- 
2.19.2


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

* [PATCH net-next 4/5] nfp: nsp: allow the use of DMA buffer
  2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
                   ` (2 preceding siblings ...)
  2019-02-27  4:19 ` [PATCH net-next 3/5] nfp: nsp: move default buffer handling into its own function Jakub Kicinski
@ 2019-02-27  4:19 ` Jakub Kicinski
  2019-02-27  4:19 ` [PATCH net-next 5/5] nfp: nsp: set higher timeout for flash bundle Jakub Kicinski
  2019-03-01 20:00 ` [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 David Miller
  5 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2019-02-27  4:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, oss-drivers, Jakub Kicinski

Newer versions of NSP can access host memory.  Simplest access
type requires all data to be in one contiguous area.  Since we
don't have the guarantee on where callers of the NSP ABI will
allocate their buffers we allocate a bounce buffer and copy
the data in and out.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
---
 .../ethernet/netronome/nfp/nfpcore/nfp_nsp.c  | 196 +++++++++++++++++-
 1 file changed, 191 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
index 28262b0fc89a..dd6256841a37 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
@@ -13,6 +13,7 @@
 #include <linux/firmware.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
+#include <linux/overflow.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
 
@@ -37,6 +38,7 @@
 #define NSP_COMMAND		0x08
 #define   NSP_COMMAND_OPTION	GENMASK_ULL(63, 32)
 #define   NSP_COMMAND_CODE	GENMASK_ULL(31, 16)
+#define   NSP_COMMAND_DMA_BUF	BIT_ULL(1)
 #define   NSP_COMMAND_START	BIT_ULL(0)
 
 /* CPP address to retrieve the data from */
@@ -49,9 +51,12 @@
 #define   NSP_DFLT_BUFFER_ADDRESS	GENMASK_ULL(39, 0)
 
 #define NSP_DFLT_BUFFER_CONFIG	0x20
+#define   NSP_DFLT_BUFFER_DMA_CHUNK_ORDER	GENMASK_ULL(63, 58)
 #define   NSP_DFLT_BUFFER_SIZE_4KB	GENMASK_ULL(15, 8)
 #define   NSP_DFLT_BUFFER_SIZE_MB	GENMASK_ULL(7, 0)
 
+#define NFP_CAP_CMD_DMA_SG	0x28
+
 #define NSP_MAGIC		0xab10
 #define NSP_MAJOR		0
 #define NSP_MINOR		8
@@ -92,6 +97,16 @@ enum nfp_nsp_cmd {
 	SPCODE_VERSIONS		= 21, /* Report FW versions */
 };
 
+struct nfp_nsp_dma_buf {
+	__le32 chunk_cnt;
+	__le32 reserved[3];
+	struct {
+		__le32 size;
+		__le32 reserved;
+		__le64 addr;
+	} descs[];
+};
+
 static const struct {
 	int code;
 	const char *msg;
@@ -120,6 +135,7 @@ struct nfp_nsp {
 /**
  * struct nfp_nsp_command_arg - NFP command argument structure
  * @code:	NFP SP Command Code
+ * @dma:	@buf points to a host buffer, not NSP buffer
  * @timeout_sec:Timeout value to wait for completion in seconds
  * @option:	NFP SP Command Argument
  * @buf:	NFP SP Buffer Address
@@ -127,6 +143,7 @@ struct nfp_nsp {
  */
 struct nfp_nsp_command_arg {
 	u16 code;
+	bool dma;
 	unsigned int timeout_sec;
 	u32 option;
 	u64 buf;
@@ -350,6 +367,7 @@ __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
 	err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command,
 			     FIELD_PREP(NSP_COMMAND_OPTION, arg->option) |
 			     FIELD_PREP(NSP_COMMAND_CODE, arg->code) |
+			     FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) |
 			     FIELD_PREP(NSP_COMMAND_START, 1));
 	if (err < 0)
 		return err;
@@ -456,10 +474,174 @@ nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
 	return ret;
 }
 
+static int
+nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp,
+			   struct nfp_nsp_command_buf_arg *arg,
+			   unsigned int max_size, unsigned int chunk_order,
+			   unsigned int dma_order)
+{
+	struct nfp_cpp *cpp = nsp->cpp;
+	struct nfp_nsp_dma_buf *desc;
+	struct {
+		dma_addr_t dma_addr;
+		unsigned long len;
+		void *chunk;
+	} *chunks;
+	size_t chunk_size, dma_size;
+	dma_addr_t dma_desc;
+	struct device *dev;
+	unsigned long off;
+	int i, ret, nseg;
+	size_t desc_sz;
+
+	chunk_size = BIT_ULL(chunk_order);
+	dma_size = BIT_ULL(dma_order);
+	nseg = DIV_ROUND_UP(max_size, chunk_size);
+
+	chunks = kzalloc(array_size(sizeof(*chunks), nseg), GFP_KERNEL);
+	if (!chunks)
+		return -ENOMEM;
+
+	off = 0;
+	ret = -ENOMEM;
+	for (i = 0; i < nseg; i++) {
+		unsigned long coff;
+
+		chunks[i].chunk = kmalloc(chunk_size,
+					  GFP_KERNEL | __GFP_NOWARN);
+		if (!chunks[i].chunk)
+			goto exit_free_prev;
+
+		chunks[i].len = min_t(u64, chunk_size, max_size - off);
+
+		coff = 0;
+		if (arg->in_size > off) {
+			coff = min_t(u64, arg->in_size - off, chunk_size);
+			memcpy(chunks[i].chunk, arg->in_buf + off, coff);
+		}
+		memset(chunks[i].chunk + coff, 0, chunk_size - coff);
+
+		off += chunks[i].len;
+	}
+
+	dev = nfp_cpp_device(cpp)->parent;
+
+	for (i = 0; i < nseg; i++) {
+		dma_addr_t addr;
+
+		addr = dma_map_single(dev, chunks[i].chunk, chunks[i].len,
+				      DMA_BIDIRECTIONAL);
+		chunks[i].dma_addr = addr;
+
+		ret = dma_mapping_error(dev, addr);
+		if (ret)
+			goto exit_unmap_prev;
+
+		if (WARN_ONCE(round_down(addr, dma_size) !=
+			      round_down(addr + chunks[i].len - 1, dma_size),
+			      "unaligned DMA address: %pad %lu %zd\n",
+			      &addr, chunks[i].len, dma_size)) {
+			ret = -EFAULT;
+			i++;
+			goto exit_unmap_prev;
+		}
+	}
+
+	desc_sz = struct_size(desc, descs, nseg);
+	desc = kmalloc(desc_sz, GFP_KERNEL);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto exit_unmap_all;
+	}
+
+	desc->chunk_cnt = cpu_to_le32(nseg);
+	for (i = 0; i < nseg; i++) {
+		desc->descs[i].size = cpu_to_le32(chunks[i].len);
+		desc->descs[i].addr = cpu_to_le64(chunks[i].dma_addr);
+	}
+
+	dma_desc = dma_map_single(dev, desc, desc_sz, DMA_TO_DEVICE);
+	ret = dma_mapping_error(dev, dma_desc);
+	if (ret)
+		goto exit_free_desc;
+
+	arg->arg.dma = true;
+	arg->arg.buf = dma_desc;
+	ret = __nfp_nsp_command(nsp, &arg->arg);
+	if (ret < 0)
+		goto exit_unmap_desc;
+
+	i = 0;
+	off = 0;
+	while (off < arg->out_size) {
+		unsigned int len;
+
+		len = min_t(u64, chunks[i].len, arg->out_size - off);
+		memcpy(arg->out_buf + off, chunks[i].chunk, len);
+		off += len;
+		i++;
+	}
+
+exit_unmap_desc:
+	dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE);
+exit_free_desc:
+	kfree(desc);
+exit_unmap_all:
+	i = nseg;
+exit_unmap_prev:
+	while (--i >= 0)
+		dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len,
+				 DMA_BIDIRECTIONAL);
+	i = nseg;
+exit_free_prev:
+	while (--i >= 0)
+		kfree(chunks[i].chunk);
+	kfree(chunks);
+	if (ret < 0)
+		nfp_err(cpp, "NSP: SG DMA failed for command 0x%04x: %d (sz:%d cord:%d)\n",
+			arg->arg.code, ret, max_size, chunk_order);
+	return ret;
+}
+
+static int
+nfp_nsp_command_buf_dma(struct nfp_nsp *nsp,
+			struct nfp_nsp_command_buf_arg *arg,
+			unsigned int max_size, unsigned int dma_order)
+{
+	unsigned int chunk_order, buf_order;
+	struct nfp_cpp *cpp = nsp->cpp;
+	bool sg_ok;
+	u64 reg;
+	int err;
+
+	buf_order = order_base_2(roundup_pow_of_two(max_size));
+
+	err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
+			    nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG,
+			    &reg);
+	if (err < 0)
+		return err;
+	sg_ok = reg & BIT_ULL(arg->arg.code - 1);
+
+	if (!sg_ok) {
+		if (buf_order > dma_order) {
+			nfp_err(cpp, "NSP: can't service non-SG DMA for command 0x%04x\n",
+				arg->arg.code);
+			return -ENOMEM;
+		}
+		chunk_order = buf_order;
+	} else {
+		chunk_order = min_t(unsigned int, dma_order, PAGE_SHIFT);
+	}
+
+	return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order,
+					  dma_order);
+}
+
 static int
 nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
 {
-	unsigned int def_size, max_size;
+	unsigned int dma_order, def_size, max_size;
 	struct nfp_cpp *cpp = nsp->cpp;
 	u64 reg;
 	int err;
@@ -484,12 +666,16 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
 	max_size = max(arg->in_size, arg->out_size);
 	def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
 		   FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
-	if (def_size >= max_size)
+	dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg);
+	if (def_size >= max_size) {
 		return nfp_nsp_command_buf_def(nsp, arg);
+	} else if (!dma_order) {
+		nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
+			arg->arg.code, def_size, max_size);
+		return -EINVAL;
+	}
 
-	nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
-		arg->arg.code, def_size, max_size);
-	return -EINVAL;
+	return nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order);
 }
 
 int nfp_nsp_wait(struct nfp_nsp *state)
-- 
2.19.2


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

* [PATCH net-next 5/5] nfp: nsp: set higher timeout for flash bundle
  2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
                   ` (3 preceding siblings ...)
  2019-02-27  4:19 ` [PATCH net-next 4/5] nfp: nsp: allow the use of DMA buffer Jakub Kicinski
@ 2019-02-27  4:19 ` Jakub Kicinski
  2019-03-01 20:00 ` [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 David Miller
  5 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2019-02-27  4:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, oss-drivers, Dirk van der Merwe

From: Dirk van der Merwe <dirk.vandermerwe@netronome.com>

The management firmware now supports being passed a bundle with
multiple components to be stored in flash at once. This makes it
easier to update all components to a known state with a single
user command, however, this also has the potential to increase
the time required to perform the update significantly.

The management firmware only updates the components out of a bundle
which are outdated, however, we need to make sure we can handle
the absolute worst case where a CPLD update can take a long time
to perform.

We set a very conservative total timeout of 900s which already
adds a contingency.

Signed-off-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
index dd6256841a37..3a4e224a64b7 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
@@ -799,10 +799,7 @@ int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw)
 		{
 			.code		= SPCODE_NSP_WRITE_FLASH,
 			.option		= fw->size,
-			/* The flash time is specified to take a maximum of 70s
-			 * so we add an additional factor to this spec time.
-			 */
-			.timeout_sec	= 2.5 * 70,
+			.timeout_sec	= 900,
 		},
 		.in_buf		= fw->data,
 		.in_size	= fw->size,
-- 
2.19.2


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

* Re: [PATCH net-next 0/5] nfp: control processor DMA support and RJ45
  2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
                   ` (4 preceding siblings ...)
  2019-02-27  4:19 ` [PATCH net-next 5/5] nfp: nsp: set higher timeout for flash bundle Jakub Kicinski
@ 2019-03-01 20:00 ` David Miller
  5 siblings, 0 replies; 7+ messages in thread
From: David Miller @ 2019-03-01 20:00 UTC (permalink / raw)
  To: jakub.kicinski; +Cc: netdev, oss-drivers

From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Tue, 26 Feb 2019 20:19:28 -0800

> This series starts with adding support for reporting twisted pair
> media type in ethtool.
> 
> Remaining patches add support for using DMA with the control/service
> processor.  Currently we always copy the command data into card's
> memory.  DMA support allows us to have the NSP read the data from
> host memory by itself.  Unfortunately, the FW loading and flashing
> cannot directly map the buffers for DMA because (a) the firmware
> ABI returns const buffers, and (b) the buffers may be vmalloc()ed
> in many mysterious/unmappable way.  So just bite the bullet -
> allocate new host buffer for the command and copy.
> 
> As Dirk explains, the NSP now supports updating all FWs at once
> which means the max flashing time grew significantly.  He bumps
> the max wait to avoid timeouts.

Series applied, thanks Jakub.

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

end of thread, other threads:[~2019-03-01 20:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-27  4:19 [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 Jakub Kicinski
2019-02-27  4:19 ` [PATCH net-next 1/5] nfp: report RJ45 connector in ethtool Jakub Kicinski
2019-02-27  4:19 ` [PATCH net-next 2/5] nfp: nsp: use fractional size of the buffer Jakub Kicinski
2019-02-27  4:19 ` [PATCH net-next 3/5] nfp: nsp: move default buffer handling into its own function Jakub Kicinski
2019-02-27  4:19 ` [PATCH net-next 4/5] nfp: nsp: allow the use of DMA buffer Jakub Kicinski
2019-02-27  4:19 ` [PATCH net-next 5/5] nfp: nsp: set higher timeout for flash bundle Jakub Kicinski
2019-03-01 20:00 ` [PATCH net-next 0/5] nfp: control processor DMA support and RJ45 David Miller

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