Commit 808cee16 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-lan966x-add-support-for-fdma'

Horatiu Vultur says:

====================
net: lan966x: Add support for FDMA

Currently when injecting or extracting a frame from CPU, the frame
is given to the HW each word at a time. There is another way to
inject/extract frames from CPU using FDMA(Frame Direct Memory Access).
In this way the entire frame is given to the HW. This improves both
RX and TX bitrate.
====================

Tested-by: Michael Walle <michael@walle.cc> # on kontron-kswitch-d10
Link: https://lore.kernel.org/r/20220408070357.559899-1-horatiu.vultur@microchip.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d6967d04 2ea1cbac
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -8,4 +8,4 @@ obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o
lan966x-switch-objs  := lan966x_main.o lan966x_phylink.o lan966x_port.o \
			lan966x_mac.o lan966x_ethtool.o lan966x_switchdev.o \
			lan966x_vlan.o lan966x_fdb.o lan966x_mdb.o \
			lan966x_ptp.o
			lan966x_ptp.o lan966x_fdma.o
+842 −0

File added.

Preview size limit exceeded, changes collapsed.

+48 −11
Original line number Diff line number Diff line
@@ -24,9 +24,6 @@
#define XTR_NOT_READY			0x07000080U
#define XTR_VALID_BYTES(x)		(4 - (((x) >> 24) & 3))

#define READL_SLEEP_US			10
#define READL_TIMEOUT_US		100000000

#define IO_RANGES 2

static const struct of_device_id lan966x_match[] = {
@@ -43,6 +40,7 @@ struct lan966x_main_io_resource {

static const struct lan966x_main_io_resource lan966x_main_iomap[] =  {
	{ TARGET_CPU,                   0xc0000, 0 }, /* 0xe00c0000 */
	{ TARGET_FDMA,                  0xc0400, 0 }, /* 0xe00c0400 */
	{ TARGET_ORG,                         0, 1 }, /* 0xe2000000 */
	{ TARGET_GCB,                    0x4000, 1 }, /* 0xe2004000 */
	{ TARGET_QS,                     0x8000, 1 }, /* 0xe2008000 */
@@ -343,6 +341,9 @@ static int lan966x_port_xmit(struct sk_buff *skb, struct net_device *dev)
	}

	spin_lock(&lan966x->tx_lock);
	if (port->lan966x->fdma)
		err = lan966x_fdma_xmit(skb, ifh, dev);
	else
		err = lan966x_port_ifh_xmit(skb, ifh, dev);
	spin_unlock(&lan966x->tx_lock);

@@ -353,12 +354,24 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu)
{
	struct lan966x_port *port = netdev_priv(dev);
	struct lan966x *lan966x = port->lan966x;
	int old_mtu = dev->mtu;
	int err;

	lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu),
	       lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
	dev->mtu = new_mtu;

	if (!lan966x->fdma)
		return 0;

	err = lan966x_fdma_change_mtu(lan966x);
	if (err) {
		lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(old_mtu),
		       lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
		dev->mtu = old_mtu;
	}

	return err;
}

static int lan966x_mc_unsync(struct net_device *dev, const unsigned char *addr)
@@ -432,8 +445,7 @@ bool lan966x_netdevice_check(const struct net_device *dev)
	return dev->netdev_ops == &lan966x_port_netdev_ops;
}

static bool lan966x_hw_offload(struct lan966x *lan966x, u32 port,
			       struct sk_buff *skb)
bool lan966x_hw_offload(struct lan966x *lan966x, u32 port, struct sk_buff *skb)
{
	u32 val;

@@ -514,7 +526,7 @@ static int lan966x_rx_frame_word(struct lan966x *lan966x, u8 grp, u32 *rval)
	}
}

static void lan966x_ifh_get_src_port(void *ifh, u64 *src_port)
void lan966x_ifh_get_src_port(void *ifh, u64 *src_port)
{
	packing(ifh, src_port, IFH_POS_SRCPORT + IFH_WID_SRCPORT - 1,
		IFH_POS_SRCPORT, IFH_LEN * 4, UNPACK, 0);
@@ -526,7 +538,7 @@ static void lan966x_ifh_get_len(void *ifh, u64 *len)
		IFH_POS_LEN, IFH_LEN * 4, UNPACK, 0);
}

static void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp)
void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp)
{
	packing(ifh, timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1,
		IFH_POS_TIMESTAMP, IFH_LEN * 4, UNPACK, 0);
@@ -646,6 +658,9 @@ static void lan966x_cleanup_ports(struct lan966x *lan966x)
		if (port->dev)
			unregister_netdev(port->dev);

		if (lan966x->fdma && lan966x->fdma_ndev == port->dev)
			lan966x_fdma_netdev_deinit(lan966x, port->dev);

		if (port->phylink) {
			rtnl_lock();
			lan966x_port_stop(port->dev);
@@ -665,6 +680,9 @@ static void lan966x_cleanup_ports(struct lan966x *lan966x)
		disable_irq(lan966x->ana_irq);
		lan966x->ana_irq = -ENXIO;
	}

	if (lan966x->fdma)
		devm_free_irq(lan966x->dev, lan966x->fdma_irq, lan966x);
}

static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
@@ -793,12 +811,12 @@ static void lan966x_init(struct lan966x *lan966x)
	/* Do byte-swap and expect status after last data word
	 * Extraction: Mode: manual extraction) | Byte_swap
	 */
	lan_wr(QS_XTR_GRP_CFG_MODE_SET(1) |
	lan_wr(QS_XTR_GRP_CFG_MODE_SET(lan966x->fdma ? 2 : 1) |
	       QS_XTR_GRP_CFG_BYTE_SWAP_SET(1),
	       lan966x, QS_XTR_GRP_CFG(0));

	/* Injection: Mode: manual injection | Byte_swap */
	lan_wr(QS_INJ_GRP_CFG_MODE_SET(1) |
	lan_wr(QS_INJ_GRP_CFG_MODE_SET(lan966x->fdma ? 2 : 1) |
	       QS_INJ_GRP_CFG_BYTE_SWAP_SET(1),
	       lan966x, QS_INJ_GRP_CFG(0));

@@ -1020,6 +1038,17 @@ static int lan966x_probe(struct platform_device *pdev)
		lan966x->ptp = 1;
	}

	lan966x->fdma_irq = platform_get_irq_byname(pdev, "fdma");
	if (lan966x->fdma_irq > 0) {
		err = devm_request_irq(&pdev->dev, lan966x->fdma_irq,
				       lan966x_fdma_irq_handler, 0,
				       "fdma irq", lan966x);
		if (err)
			return dev_err_probe(&pdev->dev, err, "Unable to use fdma irq");

		lan966x->fdma = true;
	}

	/* init switch */
	lan966x_init(lan966x);
	lan966x_stats_init(lan966x);
@@ -1058,8 +1087,15 @@ static int lan966x_probe(struct platform_device *pdev)
	if (err)
		goto cleanup_fdb;

	err = lan966x_fdma_init(lan966x);
	if (err)
		goto cleanup_ptp;

	return 0;

cleanup_ptp:
	lan966x_ptp_deinit(lan966x);

cleanup_fdb:
	lan966x_fdb_deinit(lan966x);

@@ -1079,6 +1115,7 @@ static int lan966x_remove(struct platform_device *pdev)
{
	struct lan966x *lan966x = platform_get_drvdata(pdev);

	lan966x_fdma_deinit(lan966x);
	lan966x_cleanup_ports(lan966x);

	cancel_delayed_work_sync(&lan966x->stats_work);
+117 −0

File changed.

Preview size limit exceeded, changes collapsed.

+3 −0
Original line number Diff line number Diff line
@@ -393,6 +393,9 @@ void lan966x_port_init(struct lan966x_port *port)

	lan966x_port_config_down(port);

	if (lan966x->fdma)
		lan966x_fdma_netdev_init(lan966x, port->dev);

	if (config->portmode != PHY_INTERFACE_MODE_QSGMII)
		return;

Loading