Skip to content

Commit

Permalink
net: microchip: add FDMA library
Browse files Browse the repository at this point in the history
Add new FDMA library for interacting with the FDMA engine on Microchip
Sparx5 and lan966x switch chips, in an effort to reduce duplicate code
and provide a common set of symbols and functions.

Signed-off-by: Daniel Machon <daniel.machon@microchip.com>
Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
Reviewed-by: Jens Emil Schulz Østergaard <jensemil.schulzostergaard@microchip.com>
Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Daniel Machon authored and David S. Miller committed Sep 4, 2024
1 parent 3d4d0fa commit 30e48a7
Show file tree
Hide file tree
Showing 7 changed files with 417 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/microchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ config LAN743X
source "drivers/net/ethernet/microchip/lan966x/Kconfig"
source "drivers/net/ethernet/microchip/sparx5/Kconfig"
source "drivers/net/ethernet/microchip/vcap/Kconfig"
source "drivers/net/ethernet/microchip/fdma/Kconfig"

endif # NET_VENDOR_MICROCHIP
1 change: 1 addition & 0 deletions drivers/net/ethernet/microchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
obj-$(CONFIG_LAN966X_SWITCH) += lan966x/
obj-$(CONFIG_SPARX5_SWITCH) += sparx5/
obj-$(CONFIG_VCAP) += vcap/
obj-$(CONFIG_FDMA) += fdma/
18 changes: 18 additions & 0 deletions drivers/net/ethernet/microchip/fdma/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Microchip FDMA API configuration
#

if NET_VENDOR_MICROCHIP

config FDMA
bool "FDMA API"
help
Provides the basic FDMA functionality for multiple Microchip
switchcores.

Say Y here if you want to build the FDMA API that provides a common
set of functions and data structures for interacting with the Frame
DMA engine in multiple microchip switchcores.

endif # NET_VENDOR_MICROCHIP
7 changes: 7 additions & 0 deletions drivers/net/ethernet/microchip/fdma/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for Microchip FDMA
#

obj-$(CONFIG_FDMA) += fdma.o
fdma-y += fdma_api.o
146 changes: 146 additions & 0 deletions drivers/net/ethernet/microchip/fdma/fdma_api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0+

#include "fdma_api.h"

#include <linux/bits.h>
#include <linux/etherdevice.h>
#include <linux/types.h>

/* Add a DB to a DCB, providing a callback for getting the DB dataptr. */
static int __fdma_db_add(struct fdma *fdma, int dcb_idx, int db_idx, u64 status,
int (*cb)(struct fdma *fdma, int dcb_idx,
int db_idx, u64 *dataptr))
{
struct fdma_db *db = fdma_db_get(fdma, dcb_idx, db_idx);

db->status = status;

return cb(fdma, dcb_idx, db_idx, &db->dataptr);
}

/* Add a DB to a DCB, using the callback set in the fdma_ops struct. */
int fdma_db_add(struct fdma *fdma, int dcb_idx, int db_idx, u64 status)
{
return __fdma_db_add(fdma,
dcb_idx,
db_idx,
status,
fdma->ops.dataptr_cb);
}

/* Add a DCB with callbacks for getting the DB dataptr and the DCB nextptr. */
int __fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status,
int (*dcb_cb)(struct fdma *fdma, int dcb_idx, u64 *nextptr),
int (*db_cb)(struct fdma *fdma, int dcb_idx, int db_idx,
u64 *dataptr))
{
struct fdma_dcb *dcb = fdma_dcb_get(fdma, dcb_idx);
int i, err;

for (i = 0; i < fdma->n_dbs; i++) {
err = __fdma_db_add(fdma, dcb_idx, i, status, db_cb);
if (unlikely(err))
return err;
}

err = dcb_cb(fdma, dcb_idx, &fdma->last_dcb->nextptr);
if (unlikely(err))
return err;

fdma->last_dcb = dcb;

dcb->nextptr = FDMA_DCB_INVALID_DATA;
dcb->info = info;

return 0;
}
EXPORT_SYMBOL_GPL(__fdma_dcb_add);

/* Add a DCB, using the preset callbacks in the fdma_ops struct. */
int fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status)
{
return __fdma_dcb_add(fdma,
dcb_idx,
info, status,
fdma->ops.nextptr_cb,
fdma->ops.dataptr_cb);
}
EXPORT_SYMBOL_GPL(fdma_dcb_add);

/* Initialize the DCB's and DB's. */
int fdma_dcbs_init(struct fdma *fdma, u64 info, u64 status)
{
int i, err;

fdma->last_dcb = fdma->dcbs;
fdma->db_index = 0;
fdma->dcb_index = 0;

for (i = 0; i < fdma->n_dcbs; i++) {
err = fdma_dcb_add(fdma, i, info, status);
if (err)
return err;
}

return 0;
}
EXPORT_SYMBOL_GPL(fdma_dcbs_init);

/* Allocate coherent DMA memory for FDMA. */
int fdma_alloc_coherent(struct device *dev, struct fdma *fdma)
{
fdma->dcbs = dma_alloc_coherent(dev,
fdma->size,
&fdma->dma,
GFP_KERNEL);
if (!fdma->dcbs)
return -ENOMEM;

return 0;
}
EXPORT_SYMBOL_GPL(fdma_alloc_coherent);

/* Allocate physical memory for FDMA. */
int fdma_alloc_phys(struct fdma *fdma)
{
fdma->dcbs = kzalloc(fdma->size, GFP_KERNEL);
if (!fdma->dcbs)
return -ENOMEM;

fdma->dma = virt_to_phys(fdma->dcbs);

return 0;
}
EXPORT_SYMBOL_GPL(fdma_alloc_phys);

/* Free coherent DMA memory. */
void fdma_free_coherent(struct device *dev, struct fdma *fdma)
{
dma_free_coherent(dev, fdma->size, fdma->dcbs, fdma->dma);
}
EXPORT_SYMBOL_GPL(fdma_free_coherent);

/* Free virtual memory. */
void fdma_free_phys(struct fdma *fdma)
{
kfree(fdma->dcbs);
}
EXPORT_SYMBOL_GPL(fdma_free_phys);

/* Get the size of the FDMA memory */
u32 fdma_get_size(struct fdma *fdma)
{
return ALIGN(sizeof(struct fdma_dcb) * fdma->n_dcbs, PAGE_SIZE);
}
EXPORT_SYMBOL_GPL(fdma_get_size);

/* Get the size of the FDMA memory. This function is only applicable if the
* dataptr addresses and DCB's are in contiguous memory.
*/
u32 fdma_get_size_contiguous(struct fdma *fdma)
{
return ALIGN(fdma->n_dcbs * sizeof(struct fdma_dcb) +
fdma->n_dcbs * fdma->n_dbs * fdma->db_size,
PAGE_SIZE);
}
EXPORT_SYMBOL_GPL(fdma_get_size_contiguous);
Loading

0 comments on commit 30e48a7

Please sign in to comment.