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.
next prev parent 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).