mbox series

[v7,0/5] dma: add channels support

Message ID 20181110210649.8992-1-grygorii.strashko@ti.com
Headers show
Series dma: add channels support | expand

Message

Grygorii Strashko Nov. 10, 2018, 9:06 p.m. UTC
Hi All,

This series is the next try to add DMA channels support for DMA controllers
which last version was posted by Álvaro Fernández Rojas [1].
i've kept version numbering.

Comparing to the original post I've added few changes:
 - added possibility to pass DMA driver/channel's specific data per each transfer
 using additional parameter "metadata" in dma_send/dma_receive() API.
 For example, port number for network packets to be directed to the
 specific port on multi port ethernet controllers.
 - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
 DEV_TO_MEM transfer using DMA streaming channels which is usual case
 for Networking.
 - added dma-uclass test
 - removed unused function dma_get_by_index_platdata()
 - updated comments

Hence, originally DMA channels support was introduced to add support for
"bmips: add bcm6348-enet support" - that series can be easily updated following
DMA channels API changes (if still actual).

Patches 5-6 - Here I'm providing DMA and networking drivers for the new
TI AM65x SoC [2] as an illustration of DMA channels API usage only. Unfortunately,
those drivers are still under development so NOT-FOR-MERGE (!will not build!)
- we'd like code/bindings to be accepted in LKML first.
Full sources can be found at [3].

[1] https://patchwork.ozlabs.org/cover/881642/
[2] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf
[3] git@git.ti.com:~gragst/ti-u-boot/gragsts-ti-u-boot.git
    branch: master-am6-dma-wip
===

A DMA is a feature of computer systems that allows certain hardware
subsystems to access main system memory, independent of the CPU.
DMA channels are typically generated externally to the HW module
consuming them, by an entity this API calls a DMA provider. This API
provides a standard means for drivers to enable and disable DMAs, and to
copy, send and receive data using DMA.

DMA channel API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

A driver that implements UCLASS_DMA is a DMA provider. A provider will
often implement multiple separate DMAs channels, since the hardware it manages
often has this capability. dma_uclass.h describes the interface which
DMA providers must implement.

DMA consumers/clients are the HW modules driven by the DMA channels. 

DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
Note. In u-boot dma_send() is sync operation always - it'll start transfer and
will poll for it to complete:
- get/request dma channel
	struct dma dma_tx;
	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_tx);
	if (ret) ...

- dma transmit DMA_MEM_TO_DEV.
	struct ti_drv_packet_data packet_data;
	
	packet_data.opt1 = val1;
	packet_data.opt2 = val2;
	ret = dma_send(&dma_tx, packet, length, &packet_data);
	if (ret) ..

DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
Note. dma_receive() is sync operation always - it'll start transfer
(if required) and will poll for it to complete (or for any previously
configured dev2mem transfer to complete):
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	
	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
	if (ret < 0) ...

DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
networking). Networking subsystem allows to configure and use few receive
buffers (dev2mem), as Networking RX DMA channels usually implemented
as streaming interface
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...
	
	for (i = 0; i < RX_DESC_NUM; i++) {
		ret = dma_prepare_rcv_buf(&dma_rx,
					  net_rx_packets[i],
					  RX_BUF_SIZE);
		if (ret) ...
	}

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	void *packet;
	
	len = dma_receive(&dma_rx, &packet, &packet_data);
	if (ret < 0) ..
	
	/* packet - points on buffer prepared by dma_prepare_rcv_buf().
	   process packet*/
	
	- return buffer back to DAM channel
	ret = dma_prepare_rcv_buf(&dma_rx,
				  net_rx_packets[rx_next],
				  RX_BUF_SIZE);

changes in v7:
 - copyright fixed as suggested by Tom Rini
 - added "Reviewed-by" tags

v1: http://patchwork.ozlabs.org/cover/987948/

Grygorii Strashko (2):
  test: dma: add dma-uclass test
  net: ethernet: ti: introduce am654 gigabit eth switch subsystem driver

Vignesh R (1):
  dma: ti: add driver to K3 UDMA

Álvaro Fernández Rojas (2):
  dma: move dma_ops to dma-uclass.h
  dma: add channels support

 arch/sandbox/dts/test.dts         |    8 +
 configs/sandbox_defconfig         |    3 +
 drivers/dma/Kconfig               |   16 +
 drivers/dma/Makefile              |    3 +
 drivers/dma/dma-uclass.c          |  183 +++-
 drivers/dma/sandbox-dma-test.c    |  282 +++++++
 drivers/dma/ti-edma3.c            |    2 +-
 drivers/dma/ti/Kconfig            |   14 +
 drivers/dma/ti/Makefile           |    3 +
 drivers/dma/ti/k3-udma-hwdef.h    |  184 ++++
 drivers/dma/ti/k3-udma.c          | 1679 +++++++++++++++++++++++++++++++++++++
 drivers/net/Kconfig               |    8 +
 drivers/net/Makefile              |    1 +
 drivers/net/am65-cpsw-nuss.c      |  962 +++++++++++++++++++++
 include/dma-uclass.h              |  128 +++
 include/dma.h                     |  282 ++++++-
 include/dt-bindings/dma/k3-udma.h |   26 +
 include/linux/soc/ti/ti-udma.h    |   24 +
 test/dm/Makefile                  |    1 +
 test/dm/dma.c                     |  123 +++
 20 files changed, 3902 insertions(+), 30 deletions(-)
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 drivers/dma/ti/Kconfig
 create mode 100644 drivers/dma/ti/Makefile
 create mode 100644 drivers/dma/ti/k3-udma-hwdef.h
 create mode 100644 drivers/dma/ti/k3-udma.c
 create mode 100644 drivers/net/am65-cpsw-nuss.c
 create mode 100644 include/dma-uclass.h
 create mode 100644 include/dt-bindings/dma/k3-udma.h
 create mode 100644 include/linux/soc/ti/ti-udma.h
 create mode 100644 test/dm/dma.c

Comments

Tom Rini Nov. 26, 2018, 11:15 p.m. UTC | #1
On Mon, Nov 26, 2018 at 07:00:08PM +0100, Álvaro Fernández Rojas wrote:

> In order to add bcm6348-enet support, dma-uclass must be extended to support

> dma channels and reworked to operate like the other dm uclass (clk, reset...).

> 

> ===

> 

> A DMA is a feature of computer systems that allows certain hardware

> subsystems to access main system memory, independent of the CPU.

> DMA channels are typically generated externally to the HW module

> consuming them, by an entity this API calls a DMA provider. This API

> provides a standard means for drivers to enable and disable DMAs, and to

> copy, send and receive data using DMA.

> 

> DMA channel API:

>  dma_get_by_index()

>  dma_get_by_name()

>  dma_request()

>  dma_free()

>  dma_enable()

>  dma_disable()

>  dma_prepare_rcv_buf()

>  dma_receive()

>  dma_send()

> 

> A driver that implements UCLASS_DMA is a DMA provider. A provider will

> often implement multiple separate DMAs channels, since the hardware it manages

> often has this capability. dma_uclass.h describes the interface which

> DMA providers must implement.

> 

> DMA consumers/clients are the HW modules driven by the DMA channels. 

> 

> DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).

> Note. In u-boot dma_send() is sync operation always - it'll start transfer and

> will poll for it to complete:

> - get/request dma channel

> 	struct dma dma_tx;

> 	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);

> 	if (ret) ...

> 

> - enable dma channel

> 	ret = dma_enable(&dma_tx);

> 	if (ret) ...

> 

> - dma transmit DMA_MEM_TO_DEV.

> 	struct ti_drv_packet_data packet_data;

> 	

> 	packet_data.opt1 = val1;

> 	packet_data.opt2 = val2;

> 	ret = dma_send(&dma_tx, packet, length, &packet_data);

> 	if (ret) ..

> 

> DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).

> Note. dma_receive() is sync operation always - it'll start transfer

> (if required) and will poll for it to complete (or for any previously

> configured dev2mem transfer to complete):

> - get/request dma channel

> 	struct dma dma_rx;

> 	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);

> 	if (ret) ...

> 

> - enable dma channel

> 	ret = dma_enable(&dma_rx);

> 	if (ret) ...

> 

> - dma receive DMA_DEV_TO_MEM.

> 	struct ti_drv_packet_data packet_data;

> 	

> 	len = dma_receive(&dma_rx, (void **)packet, &packet_data);

> 	if (ret < 0) ...

> 

> DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on

> networking). Networking subsystem allows to configure and use few receive

> buffers (dev2mem), as Networking RX DMA channels usually implemented

> as streaming interface

> - get/request dma channel

> 	struct dma dma_rx;

> 	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);

> 	if (ret) ...

> 	

> 	for (i = 0; i < RX_DESC_NUM; i++) {

> 		ret = dma_prepare_rcv_buf(&dma_rx,

> 					  net_rx_packets[i],

> 					  RX_BUF_SIZE);

> 		if (ret) ...

> 	}

> 

> - enable dma channel

> 	ret = dma_enable(&dma_rx);

> 	if (ret) ...

> 

> - dma receive DMA_DEV_TO_MEM.

> 	struct ti_drv_packet_data packet_data;

> 	void *packet;

> 	

> 	len = dma_receive(&dma_rx, &packet, &packet_data);

> 	if (ret < 0) ..

> 	

> 	/* packet - points on buffer prepared by dma_prepare_rcv_buf().

> 	   process packet*/

> 	

> 	- return buffer back to DAM channel

> 	ret = dma_prepare_rcv_buf(&dma_rx,

> 				  net_rx_packets[rx_next],

> 				  RX_BUF_SIZE);

> 


Can you please split this into 2 parts, the generic DMA portion, and the
bcm6368-enet/etc part?  Thanks!

-- 
Tom