devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thor Thayer <thor.thayer@linux.intel.com>
To: dwesterg@gmail.com, netdev@vger.kernel.org, dinguyen@kernel.org,
	richardcochran@gmail.com, davem@davemloft.net,
	vbridger@opensource.altera.com, robh+dt@kernel.org,
	"mark.rutland@arm.commark.rutland"@arm.com,
	devicetree@vger.kernel.org, hean.loong.ong@intel.com
Cc: Dalon Westergreen <dalon.westergreen@intel.com>
Subject: Re: [PATCH v2 net-next 09/10] net: eth: altera: add msgdma prefetcher
Date: Tue, 18 Dec 2018 10:33:59 -0600	[thread overview]
Message-ID: <bf6d5920-fa90-abd7-65a5-19d48b3e6a7e@linux.intel.com> (raw)
In-Reply-To: <20181213175252.21143-10-dalon.westergreen@linux.intel.com>

Hi Dalon,

On 12/13/18 11:52 AM, dwesterg@gmail.com wrote:
> From: Dalon Westergreen <dalon.westergreen@intel.com>
> 
> Add support for the mSGDMA prefetcher.  The prefetcher adds support
> for a linked list of descriptors in system memory.  The prefetcher
> feeds these to the mSGDMA dispatcher.
> 
> The prefetcher is configured to poll for the next descriptor in the
> list to be owned by hardware, then pass the descriptor to the
> dispatcher.  It will then poll the next descriptor until it is
> owned by hardware.
> 
> The dispatcher responses are written back to the appropriate
> descriptor, and the owned by hardware bit is cleared.
> 
> The driver sets up a linked list twice the tx and rx ring sizes,
> with the last descriptor pointing back to the first.  This ensures
> that the ring of descriptors will always have inactive descriptors
> preventing the prefetcher from looping over and reusing descriptors
> inappropriately.  The prefetcher will continuously loop over these
> descriptors.  The driver modifies descriptors as required to update
> the skb address and length as well as the owned by hardware bit.
> 
> In addition to the above, the mSGDMA prefetcher can be used to
> handle rx and tx timestamps coming from the ethernet ip.  These
> can be included in the prefetcher response in the descriptor.
> 
> Signed-off-by: Dalon Westergreen <dalon.westergreen@intel.com>
> 
> ---
> Changes from v1:
>   -> Alphabatize includes
>   -> update xmit function to return type net_tx_t
>   -> Cleanup msgdms descriptor ring by making is more apparent
>      that the msgdma descriptor ring is 2 * ring_size
> ---
>   drivers/net/ethernet/altera/Makefile          |   2 +-
>   .../altera/altera_msgdma_prefetcher.c         | 432 ++++++++++++++++++
>   .../altera/altera_msgdma_prefetcher.h         |  30 ++
>   .../altera/altera_msgdmahw_prefetcher.h       |  87 ++++
>   drivers/net/ethernet/altera/altera_tse.h      |  14 +
>   drivers/net/ethernet/altera/altera_tse_main.c |  51 +++
>   6 files changed, 615 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/net/ethernet/altera/altera_msgdma_prefetcher.c
>   create mode 100644 drivers/net/ethernet/altera/altera_msgdma_prefetcher.h
>   create mode 100644 drivers/net/ethernet/altera/altera_msgdmahw_prefetcher.h
> 
> diff --git a/drivers/net/ethernet/altera/Makefile b/drivers/net/ethernet/altera/Makefile
> index 3e622b4c105a..f6627615c6c1 100644
> --- a/drivers/net/ethernet/altera/Makefile
> +++ b/drivers/net/ethernet/altera/Makefile
> @@ -5,4 +5,4 @@
>   obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
>   altera_tse-objs := altera_tse_main.o altera_tse_ethtool.o \
>   		   altera_msgdma.o altera_sgdma.o altera_utils.o \
> -		   intel_fpga_tod.o
> +		   intel_fpga_tod.o altera_msgdma_prefetcher.o
> diff --git a/drivers/net/ethernet/altera/altera_msgdma_prefetcher.c b/drivers/net/ethernet/altera/altera_msgdma_prefetcher.c
> new file mode 100644
> index 000000000000..f50ea62f687d
> --- /dev/null
> +++ b/drivers/net/ethernet/altera/altera_msgdma_prefetcher.c
> @@ -0,0 +1,432 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* MSGDMA Prefetcher driver for Altera ethernet devices
> + *
> + * Copyright (C) 2018 Intel Corporation. All rights reserved.
> + * Author(s):
> + *   Dalon Westergreen <dalon.westergreen@intel.com>
> + */
> +
> +#include <linux/list.h>
> +#include <linux/netdevice.h>
> +#include <linux/net_tstamp.h>
> +#include "altera_tse.h"
> +#include "altera_msgdma.h"
> +#include "altera_msgdmahw.h"
> +#include "altera_msgdma_prefetcher.h"
> +#include "altera_msgdmahw_prefetcher.h"
> +#include "altera_utils.h"
> +
Alphabetize includes. altera_tse.h can be just before altera_utils.h

> +int msgdma_pref_initialize(struct altera_tse_private *priv)
> +{
> +	int i;
> +	struct msgdma_pref_extended_desc *rx_descs;
> +	struct msgdma_pref_extended_desc *tx_descs;
> +	dma_addr_t rx_descsphys;
> +	dma_addr_t tx_descsphys;
> +
> +	priv->pref_rxdescphys = (dma_addr_t)0;
> +	priv->pref_txdescphys = (dma_addr_t)0;
> +
> +	/* we need to allocate more pref descriptors than ringsize to
> +	 * prevent all of the descriptors being owned by hw.  To do this
> +	 * we just allocate twice ring_size descriptors.
> +	 * rx_ring_size = priv->rx_ring_size * 2
> +	 * tx_ring_size = priv->tx_ring_size * 2
> +	 */
> +
> +	/* The prefetcher requires the descriptors to be aligned to the
> +	 * descriptor read/write master's data width which worst case is
> +	 * 512 bits.  Currently we DO NOT CHECK THIS and only support 32-bit
> +	 * prefetcher masters.
> +	 */
> +
> +	/* allocate memory for rx descriptors */
> +	priv->pref_rxdesc =
> +		dma_zalloc_coherent(priv->device,
> +				    sizeof(struct msgdma_pref_extended_desc)
> +				    * priv->rx_ring_size * 2,
> +				    &priv->pref_rxdescphys, GFP_KERNEL);
> +
> +	if (!priv->pref_rxdesc)
> +		goto err_rx;
> +
> +	/* allocate memory for tx descriptors */
> +	priv->pref_txdesc =
> +		dma_zalloc_coherent(priv->device,
> +				    sizeof(struct msgdma_pref_extended_desc)
> +				    * priv->tx_ring_size * 2,
> +				    &priv->pref_txdescphys, GFP_KERNEL);
> +
> +	if (!priv->pref_txdesc)
> +		goto err_tx;
> +
> +	/* setup base descriptor ring for tx & rx */
> +	rx_descs = (struct msgdma_pref_extended_desc *)priv->pref_rxdesc;
> +	tx_descs = (struct msgdma_pref_extended_desc *)priv->pref_txdesc;
> +	tx_descsphys = priv->pref_txdescphys;
> +	rx_descsphys = priv->pref_rxdescphys;
> +
> +	/* setup RX descriptors */
> +	priv->pref_rx_prod = 0;
> +	for (i = 0; i < priv->rx_ring_size * 2; i++) {
> +		rx_descsphys = priv->pref_rxdescphys +
> +			(((i + 1) % (priv->rx_ring_size * 2)) *
> +			sizeof(struct msgdma_pref_extended_desc));
> +		rx_descs[i].next_desc_lo = lower_32_bits(rx_descsphys);
> +		rx_descs[i].next_desc_hi = upper_32_bits(rx_descsphys);
> +		rx_descs[i].stride = MSGDMA_DESC_RX_STRIDE;
> +		/* burst set to 0 so it defaults to max configured */
> +		/* set seq number to desc number */
> +		rx_descs[i].burst_seq_num = i;
> +	}
> +
> +	/* setup TX descriptors */
> +	for (i = 0; i < priv->tx_ring_size * 2; i++) {
> +		tx_descsphys = priv->pref_txdescphys +
> +			(((i + 1) % (priv->tx_ring_size * 2)) *
> +			sizeof(struct msgdma_pref_extended_desc));
> +		tx_descs[i].next_desc_lo = lower_32_bits(tx_descsphys);
> +		tx_descs[i].next_desc_hi = upper_32_bits(tx_descsphys);
> +		tx_descs[i].stride = MSGDMA_DESC_TX_STRIDE;
> +		/* burst set to 0 so it defaults to max configured */
> +		/* set seq number to desc number */
> +		tx_descs[i].burst_seq_num = i;
> +	}
> +
> +	if (netif_msg_ifup(priv))
> +		netdev_info(priv->dev, "%s: RX Desc mem at 0x%x\n", __func__,
> +			    priv->pref_rxdescphys);
> +
> +	if (netif_msg_ifup(priv))
> +		netdev_info(priv->dev, "%s: TX Desc mem at 0x%x\n", __func__,
> +			    priv->pref_txdescphys);
> +
> +	return 0;
> +
> +err_tx:
> +	dma_free_coherent(priv->device,
> +			  sizeof(struct msgdma_pref_extended_desc)
> +			  * priv->rx_ring_size * 2,
> +			  priv->pref_rxdesc, priv->pref_rxdescphys);
> +err_rx:
> +	return -ENOMEM;
> +}
> +
> +void msgdma_pref_uninitialize(struct altera_tse_private *priv)
> +{
> +	if (priv->pref_rxdesc)
> +		dma_free_coherent(priv->device,
> +				  sizeof(struct msgdma_pref_extended_desc)
> +				  * priv->rx_ring_size * 2,
> +				  priv->pref_rxdesc, priv->pref_rxdescphys);
> +
> +	if (priv->pref_txdesc)
> +		dma_free_coherent(priv->device,
> +				  sizeof(struct msgdma_pref_extended_desc)
> +				  * priv->rx_ring_size * 2,
> +				  priv->pref_txdesc, priv->pref_txdescphys);
> +}
> +
> +void msgdma_pref_enable_txirq(struct altera_tse_private *priv)
> +{
> +	tse_set_bit(priv->tx_pref_csr, msgdma_pref_csroffs(control),
> +		    MSGDMA_PREF_CTL_GLOBAL_INTR);
> +}
> +
> +void msgdma_pref_disable_txirq(struct altera_tse_private *priv)
> +{
> +	tse_clear_bit(priv->tx_pref_csr, msgdma_pref_csroffs(control),
> +		      MSGDMA_PREF_CTL_GLOBAL_INTR);
> +}
> +
> +void msgdma_pref_clear_txirq(struct altera_tse_private *priv)
> +{
> +	csrwr32(MSGDMA_PREF_STAT_IRQ, priv->tx_pref_csr,
> +		msgdma_pref_csroffs(status));
> +}
> +
> +void msgdma_pref_enable_rxirq(struct altera_tse_private *priv)
> +{
> +	tse_set_bit(priv->rx_pref_csr, msgdma_pref_csroffs(control),
> +		    MSGDMA_PREF_CTL_GLOBAL_INTR);
> +}
> +
> +void msgdma_pref_disable_rxirq(struct altera_tse_private *priv)
> +{
> +	tse_clear_bit(priv->rx_pref_csr, msgdma_pref_csroffs(control),
> +		      MSGDMA_PREF_CTL_GLOBAL_INTR);
> +}
> +
> +void msgdma_pref_clear_rxirq(struct altera_tse_private *priv)
> +{
> +	csrwr32(MSGDMA_PREF_STAT_IRQ, priv->rx_pref_csr,
> +		msgdma_pref_csroffs(status));
> +}
> +
> +static u64 timestamp_to_ns(struct msgdma_pref_extended_desc *desc)
> +{
> +	u64 ns = 0;
> +	u64 second;
> +	u32 tmp;
> +
> +	tmp = desc->timestamp_96b[0] >> 16;
> +	tmp |= (desc->timestamp_96b[1] << 16);
> +
> +	second = desc->timestamp_96b[2];
> +	second <<= 16;
> +	second |= ((desc->timestamp_96b[1] & 0xffff0000) >> 16);
> +
> +	ns = second * NSEC_PER_SEC + tmp;
> +
> +	return ns;
> +}
> +
> +/* Setup TX descriptor
> + *   -> this should never be called when a descriptor isn't available
> + */
> +
Minor nit - you can remove this linefeed. I missed that in the previous 
review.

> +netdev_tx_t msgdma_pref_tx_buffer(struct altera_tse_private *priv,
> +				  struct tse_buffer *buffer)
> +{
> +	u32 desc_entry = priv->tx_prod % (priv->tx_ring_size * 2);
> +	struct msgdma_pref_extended_desc *tx_descs = priv->pref_txdesc;
> +
> +	/* if for some reason the descriptor is still owned by hardware */
> +	if (unlikely(tx_descs[desc_entry].desc_control
> +		     & MSGDMA_PREF_DESC_CTL_OWNED_BY_HW))
> +		return NETDEV_TX_BUSY;
> +
> +	/* write descriptor entries */
> +	tx_descs[desc_entry].len = buffer->len;
> +	tx_descs[desc_entry].read_addr_lo = lower_32_bits(buffer->dma_addr);
> +	tx_descs[desc_entry].read_addr_hi = upper_32_bits(buffer->dma_addr);
> +
> +	/* set the control bits and set owned by hw */
> +	tx_descs[desc_entry].desc_control = (MSGDMA_DESC_CTL_TX_SINGLE
> +			| MSGDMA_PREF_DESC_CTL_OWNED_BY_HW);
> +
> +	if (netif_msg_tx_queued(priv))
> +		netdev_info(priv->dev, "%s: cons: %d prod: %d",
> +			    __func__, priv->tx_cons, priv->tx_prod);
> +
> +	return NETDEV_TX_OK;
> +}
> +
> +u32 msgdma_pref_tx_completions(struct altera_tse_private *priv)
> +{
> +	u32 control;
> +	u32 ready = 0;
> +	u32 cons = priv->tx_cons;
> +	u32 desc_ringsize = priv->tx_ring_size * 2;
> +	u32 ringsize = priv->tx_ring_size;
> +	u64 ns = 0;
> +	struct msgdma_pref_extended_desc *cur;
> +	struct tse_buffer *tx_buff;
> +	struct skb_shared_hwtstamps shhwtstamp;
> +	int i;
> +
> +	if (netif_msg_tx_done(priv))
> +		for (i = 0; i < desc_ringsize; i++)
> +			netdev_info(priv->dev, "%s: desc: %d control 0x%x\n",
> +				    __func__, i,
> +				    priv->pref_txdesc[i].desc_control);
> +
> +	cur = &priv->pref_txdesc[cons % desc_ringsize];
> +	control = cur->desc_control;
> +	tx_buff = &priv->tx_ring[cons % ringsize];
> +
> +	while (!(control & MSGDMA_PREF_DESC_CTL_OWNED_BY_HW) &&
> +	       (priv->tx_prod != (cons + ready)) && control) {
> +		if (skb_shinfo(tx_buff->skb)->tx_flags & SKBTX_IN_PROGRESS) {
> +			/* Timestamping is enabled, pass timestamp back */
> +			ns = timestamp_to_ns(cur);
> +			memset(&shhwtstamp, 0,
> +			       sizeof(struct skb_shared_hwtstamps));
> +			shhwtstamp.hwtstamp = ns_to_ktime(ns);
> +			skb_tstamp_tx(tx_buff->skb, &shhwtstamp);
> +		}
> +
> +		if (netif_msg_tx_done(priv))
> +			netdev_info(priv->dev, "%s: cur: %d ts: %lld ns\n",
> +				    __func__,
> +				    ((cons + ready) % desc_ringsize), ns);
> +
> +		/* clear data */
> +		cur->desc_control = 0;
> +		cur->timestamp_96b[0] = 0;
> +		cur->timestamp_96b[1] = 0;
> +		cur->timestamp_96b[2] = 0;
> +
> +		ready++;
> +		cur = &priv->pref_txdesc[(cons + ready) % desc_ringsize];
> +		tx_buff = &priv->tx_ring[(cons + ready) % ringsize];
> +		control = cur->desc_control;
> +	}
> +
> +	return ready;
> +}
> +
> +void msgdma_pref_reset(struct altera_tse_private *priv)
> +{
> +	int counter;
> +
> +	/* turn off polling */
> +	tse_clear_bit(priv->rx_pref_csr, msgdma_pref_csroffs(control),
> +		      MSGDMA_PREF_CTL_DESC_POLL_EN);
> +	tse_clear_bit(priv->tx_pref_csr, msgdma_pref_csroffs(control),
> +		      MSGDMA_PREF_CTL_DESC_POLL_EN);
> +
> +	/* Reset the RX Prefetcher */
> +	csrwr32(MSGDMA_PREF_STAT_IRQ, priv->rx_pref_csr,
> +		msgdma_pref_csroffs(status));
> +	csrwr32(MSGDMA_PREF_CTL_RESET, priv->rx_pref_csr,
> +		msgdma_pref_csroffs(control));
> +
> +	counter = 0;
> +	while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
> +		if (tse_bit_is_clear(priv->rx_pref_csr,
> +				     msgdma_pref_csroffs(control),
> +				     MSGDMA_PREF_CTL_RESET))
> +			break;
> +		udelay(1);
> +	}
> +
> +	if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR)
> +		netif_warn(priv, drv, priv->dev,
> +			   "TSE Rx Prefetcher reset bit never cleared!\n");
> +
> +	/* clear all status bits */
> +	csrwr32(MSGDMA_PREF_STAT_IRQ, priv->tx_pref_csr,
> +		msgdma_pref_csroffs(status));
> +
These are still the same ^ and v, right?
> +	/* Reset the TX Prefetcher */
> +	csrwr32(MSGDMA_PREF_STAT_IRQ, priv->tx_pref_csr,
> +		msgdma_pref_csroffs(status));
> +	csrwr32(MSGDMA_PREF_CTL_RESET, priv->tx_pref_csr,
> +		msgdma_pref_csroffs(control));
> +
> +	counter = 0;
> +	while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
> +		if (tse_bit_is_clear(priv->tx_pref_csr,
> +				     msgdma_pref_csroffs(control),
> +				     MSGDMA_PREF_CTL_RESET))
> +			break;
> +		udelay(1);
> +	}
> +
> +	if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR)
> +		netif_warn(priv, drv, priv->dev,
> +			   "TSE Tx Prefetcher reset bit never cleared!\n");
> +
> +	/* clear all status bits */
> +	csrwr32(MSGDMA_PREF_STAT_IRQ, priv->tx_pref_csr,
> +		msgdma_pref_csroffs(status));
And this looks the same as above too but maybe that is on purpose.

> +
> +	/* Reset mSGDMA dispatchers*/
Minor nit. Can you add a space between dispatchers and */ ?

> +	msgdma_reset(priv);
> +}
> +
> +/* Setup the RX and TX prefetchers to poll the descriptor chain */
> +void msgdma_pref_start_rxdma(struct altera_tse_private *priv)
> +{
> +	csrwr32(priv->rx_poll_freq, priv->rx_pref_csr,
> +		msgdma_pref_csroffs(desc_poll_freq));
> +	csrwr32(lower_32_bits(priv->pref_rxdescphys), priv->rx_pref_csr,
> +		msgdma_pref_csroffs(next_desc_lo));
> +	csrwr32(upper_32_bits(priv->pref_rxdescphys), priv->rx_pref_csr,
> +		msgdma_pref_csroffs(next_desc_hi));
> +	tse_set_bit(priv->rx_pref_csr, msgdma_pref_csroffs(control),
> +		    MSGDMA_PREF_CTL_DESC_POLL_EN | MSGDMA_PREF_CTL_RUN);
> +}
> +
> +void msgdma_pref_start_txdma(struct altera_tse_private *priv)
> +{
> +	csrwr32(priv->tx_poll_freq, priv->tx_pref_csr,
> +		msgdma_pref_csroffs(desc_poll_freq));
> +	csrwr32(lower_32_bits(priv->pref_txdescphys), priv->tx_pref_csr,
> +		msgdma_pref_csroffs(next_desc_lo));
> +	csrwr32(upper_32_bits(priv->pref_txdescphys), priv->tx_pref_csr,
> +		msgdma_pref_csroffs(next_desc_hi));
> +	tse_set_bit(priv->tx_pref_csr, msgdma_pref_csroffs(control),
> +		    MSGDMA_PREF_CTL_DESC_POLL_EN | MSGDMA_PREF_CTL_RUN);
> +}
> +
> +/* Add MSGDMA Prefetcher Descriptor to descriptor list
> + *   -> This should never be called when a descriptor isn't available
> + */
> +void msgdma_pref_add_rx_desc(struct altera_tse_private *priv,
> +			     struct tse_buffer *rxbuffer)
> +{
> +	struct msgdma_pref_extended_desc *rx_descs = priv->pref_rxdesc;
> +	u32 desc_entry = priv->pref_rx_prod % (priv->rx_ring_size * 2);
> +
> +	/* write descriptor entries */
> +	rx_descs[desc_entry].len = priv->rx_dma_buf_sz;
> +	rx_descs[desc_entry].write_addr_lo = lower_32_bits(rxbuffer->dma_addr);
> +	rx_descs[desc_entry].write_addr_hi = upper_32_bits(rxbuffer->dma_addr);
> +
> +	/* set the control bits and set owned by hw */
> +	rx_descs[desc_entry].desc_control = (MSGDMA_DESC_CTL_END_ON_EOP
> +			| MSGDMA_DESC_CTL_END_ON_LEN
> +			| MSGDMA_DESC_CTL_TR_COMP_IRQ
> +			| MSGDMA_DESC_CTL_EARLY_IRQ
> +			| MSGDMA_DESC_CTL_TR_ERR_IRQ
> +			| MSGDMA_DESC_CTL_GO
> +			| MSGDMA_PREF_DESC_CTL_OWNED_BY_HW);
> +
> +	/* we need to keep a separate one for rx as RX_DESCRIPTORS are
> +	 * pre-configured at startup
> +	 */
Can you explain what "one" is referring to? You said it was a separate 
copy of pref_rx_prod in your last version.

> +	priv->pref_rx_prod++;
> +
> +	if (netif_msg_rx_status(priv)) {
> +		netdev_info(priv->dev, "%s: desc: %d buf: %d control 0x%x\n",
> +			    __func__, desc_entry,
> +			    priv->rx_prod % priv->rx_ring_size,
> +			    priv->pref_rxdesc[desc_entry].desc_control);
> +	}
> +}
> +
> +u32 msgdma_pref_rx_status(struct altera_tse_private *priv)
> +{
> +	u32 rxstatus = 0;
> +	u32 pktlength;
> +	u32 pktstatus;
> +	u64 ns = 0;
> +	u32 entry = priv->rx_cons % priv->rx_ring_size;
> +	u32 desc_entry = priv->rx_prod % (priv->rx_ring_size * 2);
> +	struct msgdma_pref_extended_desc *rx_descs = priv->pref_rxdesc;
> +	struct skb_shared_hwtstamps *shhwtstamp = NULL;
> +	struct tse_buffer *rx_buff = priv->rx_ring;
> +
> +	/* if the current entry is not owned by hardware, process it */
> +	if (!(rx_descs[desc_entry].desc_control
> +	      & MSGDMA_PREF_DESC_CTL_OWNED_BY_HW) &&
> +	      rx_descs[desc_entry].desc_control) {
> +		pktlength = rx_descs[desc_entry].bytes_transferred;
> +		pktstatus = rx_descs[desc_entry].desc_status;
> +		rxstatus = pktstatus;
> +		rxstatus = rxstatus << 16;
> +		rxstatus |= (pktlength & 0xffff);
> +
> +		/* get the timestamp */
> +		if (priv->hwts_rx_en) {
> +			ns = timestamp_to_ns(&rx_descs[desc_entry]);
> +			shhwtstamp = skb_hwtstamps(rx_buff[entry].skb);
> +			memset(shhwtstamp, 0,
> +			       sizeof(struct skb_shared_hwtstamps));
> +			shhwtstamp->hwtstamp = ns_to_ktime(ns);
> +		}
> +
> +		/* clear data */
> +		rx_descs[desc_entry].desc_control = 0;
> +		rx_descs[desc_entry].timestamp_96b[0] = 0;
> +		rx_descs[desc_entry].timestamp_96b[1] = 0;
> +		rx_descs[desc_entry].timestamp_96b[2] = 0;
> +
> +		if (netif_msg_rx_status(priv))
> +			netdev_info(priv->dev, "%s: desc: %d buf: %d ts: %lld ns",
> +				    __func__, desc_entry, entry, ns);
> +	}
> +	return rxstatus;
> +}
> diff --git a/drivers/net/ethernet/altera/altera_msgdma_prefetcher.h b/drivers/net/ethernet/altera/altera_msgdma_prefetcher.h
> new file mode 100644
> index 000000000000..b520b1eb85c0
> --- /dev/null
> +++ b/drivers/net/ethernet/altera/altera_msgdma_prefetcher.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* MSGDMA Prefetcher driver for Altera ethernet devices
> + *
> + * Copyright (C) 2018 Intel Corporation. All rights reserved.
> + * Author(s):
> + *   Dalon Westergreen <dalon.westergreen@intel.com>
> + */
> +
> +#ifndef __ALTERA_PREF_MSGDMA_H__
> +#define __ALTERA_PREF_MSGDMA_H__
> +
> +void msgdma_pref_reset(struct altera_tse_private *priv);
> +void msgdma_pref_enable_txirq(struct altera_tse_private *priv);
> +void msgdma_pref_enable_rxirq(struct altera_tse_private *priv);
> +void msgdma_pref_disable_rxirq(struct altera_tse_private *priv);
> +void msgdma_pref_disable_txirq(struct altera_tse_private *priv);
> +void msgdma_pref_clear_rxirq(struct altera_tse_private *priv);
> +void msgdma_pref_clear_txirq(struct altera_tse_private *priv);
> +u32 msgdma_pref_tx_completions(struct altera_tse_private *priv);
> +void msgdma_pref_add_rx_desc(struct altera_tse_private *priv,
> +			     struct tse_buffer *buffer);
> +netdev_tx_t msgdma_pref_tx_buffer(struct altera_tse_private *priv,
> +				  struct tse_buffer *buffer);
> +u32 msgdma_pref_rx_status(struct altera_tse_private *priv);
> +int msgdma_pref_initialize(struct altera_tse_private *priv);
> +void msgdma_pref_uninitialize(struct altera_tse_private *priv);
> +void msgdma_pref_start_rxdma(struct altera_tse_private *priv);
> +void msgdma_pref_start_txdma(struct altera_tse_private *priv);
> +
> +#endif /*  __ALTERA_PREF_MSGDMA_H__ */
> diff --git a/drivers/net/ethernet/altera/altera_msgdmahw_prefetcher.h b/drivers/net/ethernet/altera/altera_msgdmahw_prefetcher.h
> new file mode 100644
> index 000000000000..e0484a3dc66e
> --- /dev/null
> +++ b/drivers/net/ethernet/altera/altera_msgdmahw_prefetcher.h
> @@ -0,0 +1,87 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* MSGDMA Prefetcher driver for Altera ethernet devices
> + *
> + * Copyright (C) 2018 Intel Corporation.
> + * Contributors:
> + *   Dalon Westergreen
> + *   Thomas Chou
> + *   Ian Abbott
> + *   Yuriy Kozlov
> + *   Tobias Klauser
> + *   Andriy Smolskyy
> + *   Roman Bulgakov
> + *   Dmytro Mytarchuk
> + *   Matthew Gerlach
> + */
> +
> +#ifndef __ALTERA_MSGDMAHW_PREFETCHER_H__
> +#define __ALTERA_MSGDMAHW_PREFETCHER_H__
> +
> +/* mSGDMA prefetcher extended prefectcher descriptor format
> + */
> +struct msgdma_pref_extended_desc {
> +	/* data buffer source address low bits */
> +	u32 read_addr_lo;
> +	/* data buffer destination address low bits */
> +	u32 write_addr_lo;
> +	/* the number of bytes to transfer */
> +	u32 len;
> +	/* next descriptor low address */
> +	u32 next_desc_lo;
> +	/* number of bytes transferred */
> +	u32 bytes_transferred;
> +	u32 desc_status;
> +	u32 reserved_18;
> +	/* bit 31:24 write burst */
> +	/* bit 23:16 read burst */
> +	/* bit 15:0  sequence number */
> +	u32 burst_seq_num;
> +	/* bit 31:16 write stride */
> +	/* bit 15:0  read stride */
> +	u32 stride;
> +	/* data buffer source address high bits */
> +	u32 read_addr_hi;
> +	/* data buffer destination address high bits */
> +	u32 write_addr_hi;
> +	/* next descriptor high address */
> +	u32 next_desc_hi;
> +	/* prefetcher mod now writes these reserved bits*/
> +	/* Response bits [191:160] */
> +	u32 timestamp_96b[3];
> +	/* desc_control */
> +	u32 desc_control;
> +};
> +
> +/* mSGDMA Prefetcher Descriptor Status bits */
> +#define MSGDMA_PREF_DESC_STAT_STOPPED_ON_EARLY		BIT(8)
> +#define MSGDMA_PREF_DESC_STAT_MASK			0xFF
> +
> +/* mSGDMA Prefetcher Descriptor Control bits */
> +/* bit 31 and bits 29-0 are the same as the normal dispatcher ctl flags */
> +#define MSGDMA_PREF_DESC_CTL_OWNED_BY_HW		BIT(30)
> +
> +/* mSGDMA Prefetcher CSR */
> +struct msgdma_prefetcher_csr {
> +	u32 control;
> +	u32 next_desc_lo;
> +	u32 next_desc_hi;
> +	u32 desc_poll_freq;
> +	u32 status;
> +};
> +
> +/* mSGDMA Prefetcher Control */
> +#define MSGDMA_PREF_CTL_PARK				BIT(4)
> +#define MSGDMA_PREF_CTL_GLOBAL_INTR			BIT(3)
> +#define MSGDMA_PREF_CTL_RESET				BIT(2)
> +#define MSGDMA_PREF_CTL_DESC_POLL_EN			BIT(1)
> +#define MSGDMA_PREF_CTL_RUN				BIT(0)
> +
> +#define MSGDMA_PREF_POLL_FREQ_MASK			0xFFFF
> +
> +/* mSGDMA Prefetcher Status */
> +#define MSGDMA_PREF_STAT_IRQ				BIT(0)
> +
> +#define msgdma_pref_csroffs(a) (offsetof(struct msgdma_prefetcher_csr, a))
> +#define msgdma_pref_descroffs(a) (offsetof(struct msgdma_pref_extended_desc, a))
> +
> +#endif /* __ALTERA_MSGDMAHW_PREFETCHER_H__*/
> diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h
> index 14515a76d634..31f11fdc94b4 100644
> --- a/drivers/net/ethernet/altera/altera_tse.h
> +++ b/drivers/net/ethernet/altera/altera_tse.h
> @@ -393,6 +393,7 @@ struct altera_tse_private;
>   
>   #define ALTERA_DTYPE_SGDMA 1
>   #define ALTERA_DTYPE_MSGDMA 2
> +#define ALTERA_DTYPE_MSGDMA_PREF 3
>   
>   /* standard DMA interface for SGDMA and MSGDMA */
>   struct altera_dmaops {
> @@ -445,6 +446,19 @@ struct altera_tse_private {
>   	void __iomem *tx_dma_csr;
>   	void __iomem *tx_dma_desc;
>   
> +	/* mSGDMA Rx Prefecher address space */
> +	void __iomem *rx_pref_csr;
> +	struct msgdma_pref_extended_desc *pref_rxdesc;
> +	dma_addr_t pref_rxdescphys;
> +	u32 pref_rx_prod;
> +
> +	/* mSGDMA Tx Prefecher address space */
> +	void __iomem *tx_pref_csr;
> +	struct msgdma_pref_extended_desc *pref_txdesc;
> +	dma_addr_t pref_txdescphys;
> +	u32 rx_poll_freq;
> +	u32 tx_poll_freq;
> +
>   	/* Rx buffers queue */
>   	struct tse_buffer *rx_ring;
>   	u32 rx_cons;
> diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
> index 60f0c43a9334..5cb3ea4314f2 100644
> --- a/drivers/net/ethernet/altera/altera_tse_main.c
> +++ b/drivers/net/ethernet/altera/altera_tse_main.c
> @@ -55,6 +55,7 @@
>   #include "altera_sgdma.h"
>   #include "altera_msgdma.h"
>   #include "intel_fpga_tod.h"
> +#include "altera_msgdma_prefetcher.h"
>   
Can you alphabetize these as long as you're making changes?

>   static atomic_t instance_count = ATOMIC_INIT(~0);
>   /* Module parameters */
> @@ -1515,6 +1516,34 @@ static int altera_tse_probe(struct platform_device *pdev)
>   		priv->rxdescmem = resource_size(dma_res);
>   		priv->rxdescmem_busaddr = dma_res->start;
>   
> +	} else if (priv->dmaops &&
> +			   priv->dmaops->altera_dtype ==
> +			   ALTERA_DTYPE_MSGDMA_PREF) {
> +		/* mSGDMA Rx Prefetcher address space */
> +		ret = request_and_map(pdev, "rx_pref", &dma_res,
> +				      &priv->rx_pref_csr);
> +		if (ret)
> +			goto err_free_netdev;
> +
> +		/* mSGDMA Tx Prefetcher address space */
> +		ret = request_and_map(pdev, "tx_pref", &dma_res,
> +				      &priv->tx_pref_csr);
> +		if (ret)
> +			goto err_free_netdev;
> +
> +		/* get prefetcher rx poll frequency from device tree */
> +		if (of_property_read_u32(pdev->dev.of_node, "rx-poll-freq",
> +					 &priv->rx_poll_freq)) {
> +			dev_info(&pdev->dev, "Defaulting RX Poll Frequency to 128\n");
> +			priv->rx_poll_freq = 128;
> +		}
> +
> +		/* get prefetcher rx poll frequency from device tree */
> +		if (of_property_read_u32(pdev->dev.of_node, "tx-poll-freq",
> +					 &priv->tx_poll_freq)) {
> +			dev_info(&pdev->dev, "Defaulting TX Poll Frequency to 128\n");
> +			priv->tx_poll_freq = 128;
> +		}
>   	} else {
>   		goto err_free_netdev;
>   	}
> @@ -1773,7 +1802,29 @@ static const struct altera_dmaops altera_dtype_msgdma = {
>   	.start_txdma = NULL,
>   };
>   
> +static const struct altera_dmaops altera_dtype_prefetcher = {
> +	.altera_dtype = ALTERA_DTYPE_MSGDMA_PREF,
> +	.dmamask = 64,
> +	.reset_dma = msgdma_pref_reset,
> +	.enable_txirq = msgdma_pref_enable_txirq,
> +	.enable_rxirq = msgdma_pref_enable_rxirq,
> +	.disable_txirq = msgdma_pref_disable_txirq,
> +	.disable_rxirq = msgdma_pref_disable_rxirq,
> +	.clear_txirq = msgdma_pref_clear_txirq,
> +	.clear_rxirq = msgdma_pref_clear_rxirq,
> +	.tx_buffer = msgdma_pref_tx_buffer,
> +	.tx_completions = msgdma_pref_tx_completions,
> +	.add_rx_desc = msgdma_pref_add_rx_desc,
> +	.get_rx_status = msgdma_pref_rx_status,
> +	.init_dma = msgdma_pref_initialize,
> +	.uninit_dma = msgdma_pref_uninitialize,
> +	.start_rxdma = msgdma_pref_start_rxdma,
> +	.start_txdma = msgdma_pref_start_txdma,
> +};
> +
>   static const struct of_device_id altera_tse_ids[] = {
> +	{ .compatible = "altr,tse-msgdma-2.0",
> +		.data = &altera_dtype_prefetcher, },
>   	{ .compatible = "altr,tse-msgdma-1.0", .data = &altera_dtype_msgdma, },
>   	{ .compatible = "altr,tse-1.0", .data = &altera_dtype_sgdma, },
>   	{ .compatible = "ALTR,tse-1.0", .data = &altera_dtype_sgdma, },
> 
Hmm. I'm not sure you sent the right version - this looks very similar 
to v1.

  reply	other threads:[~2018-12-18 16:33 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-13 17:52 [PATCH v2 net-next 00/10] net: eth: altera: tse: Add PTP and mSGDMA prefetcher dwesterg
2018-12-13 17:52 ` [PATCH v2 net-next 01/10] net: eth: altera: tse_start_xmit ignores tx_buffer call response dwesterg
2018-12-18 15:32   ` Thor Thayer
2018-12-13 17:52 ` [PATCH v2 net-next 02/10] net: eth: altera: set rx and tx ring size before init_dma call dwesterg
2018-12-18 15:33   ` Thor Thayer
2018-12-13 17:52 ` [PATCH v2 net-next 03/10] net: eth: altera: fix altera_dmaops declaration dwesterg
2018-12-18 15:33   ` Thor Thayer
2018-12-13 17:52 ` [PATCH v2 net-next 04/10] net: eth: altera: add optional function to start tx dma dwesterg
2018-12-18 15:34   ` Thor Thayer
2018-12-13 17:52 ` [PATCH v2 net-next 05/10] net: eth: altera: Move common functions to altera_utils dwesterg
2018-12-18 15:37   ` Thor Thayer
2018-12-13 17:52 ` [PATCH v2 net-next 06/10] net: eth: altera: Add missing identifier names to function declarations dwesterg
2018-12-18 15:45   ` Thor Thayer
2018-12-18 15:52     ` Dalon L Westergreen
2018-12-13 17:52 ` [PATCH v2 net-next 07/10] net: eth: altera: change tx functions to type netdev_tx_t dwesterg
2018-12-18 15:48   ` Thor Thayer
2018-12-13 17:52 ` [PATCH v2 net-next 08/10] net: eth: altera: add support for ptp and timestamping dwesterg
2018-12-19  4:27   ` Richard Cochran
2018-12-19 19:27     ` Westergreen, Dalon
2018-12-13 17:52 ` [PATCH v2 net-next 09/10] net: eth: altera: add msgdma prefetcher dwesterg
2018-12-18 16:33   ` Thor Thayer [this message]
2018-12-18 17:00     ` Dalon L Westergreen
2018-12-13 17:52 ` [PATCH v2 net-next 10/10] net: eth: altera: update devicetree bindings documentation dwesterg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bf6d5920-fa90-abd7-65a5-19d48b3e6a7e@linux.intel.com \
    --to=thor.thayer@linux.intel.com \
    --cc="mark.rutland@arm.commark.rutland"@arm.com \
    --cc=dalon.westergreen@intel.com \
    --cc=davem@davemloft.net \
    --cc=devicetree@vger.kernel.org \
    --cc=dinguyen@kernel.org \
    --cc=dwesterg@gmail.com \
    --cc=hean.loong.ong@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=richardcochran@gmail.com \
    --cc=robh+dt@kernel.org \
    --cc=vbridger@opensource.altera.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).