mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00

Refreshed patches for qualcommb/ipq95xx by running make target/linux/refresh after creating a .config containing: CONFIG_TARGET_qualcommbe=y CONFIG_TARGET_qualcommbe_ipq95xx=y CONFIG_TARGET_qualcommbe_ipq95xx_DEVICE_qcom_rdp433=y Signed-off-by: John Audia <therealgraysky@proton.me> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
400 lines
11 KiB
Diff
400 lines
11 KiB
Diff
From cbcaf81cd148b77ee0570a482b536f269a9f6657 Mon Sep 17 00:00:00 2001
|
|
From: Suruchi Agarwal <quic_suruchia@quicinc.com>
|
|
Date: Thu, 21 Mar 2024 16:14:46 -0700
|
|
Subject: [PATCH 39/50] net: ethernet: qualcomm: Add netdevice support for QCOM
|
|
IPQ9574 chipset.
|
|
|
|
Add EDMA ports and netdevice operations for QCOM IPQ9574 chipset.
|
|
|
|
Change-Id: I08b2eff52b4ef0d6d428c1c416f5580ef010973f
|
|
Co-developed-by: Pavithra R <quic_pavir@quicinc.com>
|
|
Signed-off-by: Pavithra R <quic_pavir@quicinc.com>
|
|
Signed-off-by: Suruchi Agarwal <quic_suruchia@quicinc.com>
|
|
---
|
|
drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
|
|
drivers/net/ethernet/qualcomm/ppe/edma.h | 3 +
|
|
drivers/net/ethernet/qualcomm/ppe/edma_port.c | 270 ++++++++++++++++++
|
|
drivers/net/ethernet/qualcomm/ppe/edma_port.h | 31 ++
|
|
drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 19 ++
|
|
5 files changed, 324 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.c
|
|
create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.h
|
|
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/Makefile
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
|
|
@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
|
|
qcom-ppe-objs := ppe.o ppe_config.o ppe_api.o ppe_debugfs.o ppe_port.o
|
|
|
|
#EDMA
|
|
-qcom-ppe-objs += edma.o
|
|
\ No newline at end of file
|
|
+qcom-ppe-objs += edma.o edma_port.o
|
|
\ No newline at end of file
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/edma.h
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h
|
|
@@ -26,6 +26,9 @@
|
|
/* Number of PPE queue priorities supported per ARM core. */
|
|
#define EDMA_PRI_MAX_PER_CORE 8
|
|
|
|
+/* Interface ID start. */
|
|
+#define EDMA_START_IFNUM 1
|
|
+
|
|
/**
|
|
* struct edma_ring_info - EDMA ring data structure.
|
|
* @max_rings: Maximum number of rings
|
|
--- /dev/null
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c
|
|
@@ -0,0 +1,270 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+ /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ */
|
|
+
|
|
+/* EDMA port initialization, configuration and netdevice ops handling */
|
|
+
|
|
+#include <linux/etherdevice.h>
|
|
+#include <linux/net.h>
|
|
+#include <linux/netdevice.h>
|
|
+#include <linux/of_net.h>
|
|
+#include <linux/phylink.h>
|
|
+#include <linux/printk.h>
|
|
+
|
|
+#include "edma.h"
|
|
+#include "edma_port.h"
|
|
+#include "ppe_regs.h"
|
|
+
|
|
+/* Number of netdev queues. */
|
|
+#define EDMA_NETDEV_QUEUE_NUM 4
|
|
+
|
|
+static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev,
|
|
+ __maybe_unused struct sk_buff *skb,
|
|
+ __maybe_unused struct net_device *sb_dev)
|
|
+{
|
|
+ int cpu = get_cpu();
|
|
+
|
|
+ put_cpu();
|
|
+
|
|
+ return cpu;
|
|
+}
|
|
+
|
|
+static int edma_port_open(struct net_device *netdev)
|
|
+{
|
|
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
|
|
+ struct ppe_port *ppe_port;
|
|
+
|
|
+ if (!port_priv)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Inform the Linux Networking stack about the hardware capability of
|
|
+ * checksum offloading and other features. Each port is
|
|
+ * responsible to maintain the feature set it supports.
|
|
+ */
|
|
+ netdev->features |= EDMA_NETDEV_FEATURES;
|
|
+ netdev->hw_features |= EDMA_NETDEV_FEATURES;
|
|
+ netdev->vlan_features |= EDMA_NETDEV_FEATURES;
|
|
+ netdev->wanted_features |= EDMA_NETDEV_FEATURES;
|
|
+
|
|
+ ppe_port = port_priv->ppe_port;
|
|
+
|
|
+ if (ppe_port->phylink)
|
|
+ phylink_start(ppe_port->phylink);
|
|
+
|
|
+ netif_start_queue(netdev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int edma_port_close(struct net_device *netdev)
|
|
+{
|
|
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
|
|
+ struct ppe_port *ppe_port;
|
|
+
|
|
+ if (!port_priv)
|
|
+ return -EINVAL;
|
|
+
|
|
+ netif_stop_queue(netdev);
|
|
+
|
|
+ ppe_port = port_priv->ppe_port;
|
|
+
|
|
+ /* Phylink close. */
|
|
+ if (ppe_port->phylink)
|
|
+ phylink_stop(ppe_port->phylink);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int edma_port_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
|
|
+{
|
|
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
|
|
+ struct ppe_port *ppe_port;
|
|
+ int ret = -EINVAL;
|
|
+
|
|
+ if (!port_priv)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ppe_port = port_priv->ppe_port;
|
|
+ if (ppe_port->phylink)
|
|
+ return phylink_mii_ioctl(ppe_port->phylink, ifr, cmd);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int edma_port_change_mtu(struct net_device *netdev, int mtu)
|
|
+{
|
|
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
|
|
+
|
|
+ if (!port_priv)
|
|
+ return -EINVAL;
|
|
+
|
|
+ netdev->mtu = mtu;
|
|
+
|
|
+ return ppe_port_set_maxframe(port_priv->ppe_port, mtu);
|
|
+}
|
|
+
|
|
+static netdev_features_t edma_port_feature_check(__maybe_unused struct sk_buff *skb,
|
|
+ __maybe_unused struct net_device *netdev,
|
|
+ netdev_features_t features)
|
|
+{
|
|
+ return features;
|
|
+}
|
|
+
|
|
+static void edma_port_get_stats64(struct net_device *netdev,
|
|
+ struct rtnl_link_stats64 *stats)
|
|
+{
|
|
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
|
|
+
|
|
+ if (!port_priv)
|
|
+ return;
|
|
+
|
|
+ ppe_port_get_stats64(port_priv->ppe_port, stats);
|
|
+}
|
|
+
|
|
+static int edma_port_set_mac_address(struct net_device *netdev, void *macaddr)
|
|
+{
|
|
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
|
|
+ struct sockaddr *addr = (struct sockaddr *)macaddr;
|
|
+ int ret;
|
|
+
|
|
+ if (!port_priv)
|
|
+ return -EINVAL;
|
|
+
|
|
+ netdev_dbg(netdev, "AddrFamily: %d, %0x:%0x:%0x:%0x:%0x:%0x\n",
|
|
+ addr->sa_family, addr->sa_data[0], addr->sa_data[1],
|
|
+ addr->sa_data[2], addr->sa_data[3], addr->sa_data[4],
|
|
+ addr->sa_data[5]);
|
|
+
|
|
+ ret = eth_prepare_mac_addr_change(netdev, addr);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (ppe_port_set_mac_address(port_priv->ppe_port, (u8 *)addr)) {
|
|
+ netdev_err(netdev, "set mac address failed for dev: %s\n", netdev->name);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ eth_commit_mac_addr_change(netdev, addr);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct net_device_ops edma_port_netdev_ops = {
|
|
+ .ndo_open = edma_port_open,
|
|
+ .ndo_stop = edma_port_close,
|
|
+ .ndo_get_stats64 = edma_port_get_stats64,
|
|
+ .ndo_set_mac_address = edma_port_set_mac_address,
|
|
+ .ndo_validate_addr = eth_validate_addr,
|
|
+ .ndo_change_mtu = edma_port_change_mtu,
|
|
+ .ndo_eth_ioctl = edma_port_ioctl,
|
|
+ .ndo_features_check = edma_port_feature_check,
|
|
+ .ndo_select_queue = edma_port_select_queue,
|
|
+};
|
|
+
|
|
+/**
|
|
+ * edma_port_destroy - EDMA port destroy.
|
|
+ * @port: PPE port
|
|
+ *
|
|
+ * Unregister and free the netdevice.
|
|
+ */
|
|
+void edma_port_destroy(struct ppe_port *port)
|
|
+{
|
|
+ int port_id = port->port_id;
|
|
+ struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1];
|
|
+
|
|
+ unregister_netdev(netdev);
|
|
+ free_netdev(netdev);
|
|
+ ppe_port_phylink_destroy(port);
|
|
+ edma_ctx->netdev_arr[port_id - 1] = NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * edma_port_setup - EDMA port Setup.
|
|
+ * @port: PPE port
|
|
+ *
|
|
+ * Initialize and register the netdevice.
|
|
+ *
|
|
+ * Return 0 on success, negative error code on failure.
|
|
+ */
|
|
+int edma_port_setup(struct ppe_port *port)
|
|
+{
|
|
+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
|
|
+ struct device_node *np = port->np;
|
|
+ struct edma_port_priv *port_priv;
|
|
+ int port_id = port->port_id;
|
|
+ struct net_device *netdev;
|
|
+ u8 mac_addr[ETH_ALEN];
|
|
+ int ret = 0;
|
|
+ u8 *maddr;
|
|
+
|
|
+ netdev = alloc_etherdev_mqs(sizeof(struct edma_port_priv),
|
|
+ EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM);
|
|
+ if (!netdev) {
|
|
+ pr_err("alloc_etherdev() failed\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ SET_NETDEV_DEV(netdev, ppe_dev->dev);
|
|
+ netdev->dev.of_node = np;
|
|
+
|
|
+ /* max_mtu is set to 1500 in ether_setup(). */
|
|
+ netdev->max_mtu = ETH_MAX_MTU;
|
|
+
|
|
+ port_priv = netdev_priv(netdev);
|
|
+ memset((void *)port_priv, 0, sizeof(struct edma_port_priv));
|
|
+
|
|
+ port_priv->ppe_port = port;
|
|
+ port_priv->netdev = netdev;
|
|
+ netdev->watchdog_timeo = 5 * HZ;
|
|
+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
|
+ netdev->netdev_ops = &edma_port_netdev_ops;
|
|
+ netdev->gso_max_segs = GSO_MAX_SEGS;
|
|
+
|
|
+ maddr = mac_addr;
|
|
+ if (of_get_mac_address(np, maddr))
|
|
+ maddr = NULL;
|
|
+
|
|
+ if (maddr && is_valid_ether_addr(maddr)) {
|
|
+ eth_hw_addr_set(netdev, maddr);
|
|
+ } else {
|
|
+ eth_hw_addr_random(netdev);
|
|
+ netdev_info(netdev, "GMAC%d Using random MAC address - %pM\n",
|
|
+ port_id, netdev->dev_addr);
|
|
+ }
|
|
+
|
|
+ netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n",
|
|
+ netdev->name, port_id);
|
|
+
|
|
+ /* We expect 'port_id' to correspond to ports numbers on SoC.
|
|
+ * These begin from '1' and hence we subtract
|
|
+ * one when using it as an array index.
|
|
+ */
|
|
+ edma_ctx->netdev_arr[port_id - 1] = netdev;
|
|
+
|
|
+ /* Setup phylink. */
|
|
+ ret = ppe_port_phylink_setup(port, netdev);
|
|
+ if (ret) {
|
|
+ netdev_dbg(netdev, "EDMA port phylink setup for netdevice %s\n",
|
|
+ netdev->name);
|
|
+ goto port_phylink_setup_fail;
|
|
+ }
|
|
+
|
|
+ /* Register the network interface. */
|
|
+ ret = register_netdev(netdev);
|
|
+ if (ret) {
|
|
+ netdev_dbg(netdev, "Error registering netdevice %s\n",
|
|
+ netdev->name);
|
|
+ goto register_netdev_fail;
|
|
+ }
|
|
+
|
|
+ netdev_dbg(netdev, "Setup EDMA port GMAC%d done\n", port_id);
|
|
+ return ret;
|
|
+
|
|
+register_netdev_fail:
|
|
+ ppe_port_phylink_destroy(port);
|
|
+port_phylink_setup_fail:
|
|
+ free_netdev(netdev);
|
|
+ edma_ctx->netdev_arr[port_id - 1] = NULL;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h
|
|
@@ -0,0 +1,31 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-only
|
|
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __EDMA_PORTS__
|
|
+#define __EDMA_PORTS__
|
|
+
|
|
+#include "ppe_port.h"
|
|
+
|
|
+#define EDMA_NETDEV_FEATURES (NETIF_F_FRAGLIST \
|
|
+ | NETIF_F_SG \
|
|
+ | NETIF_F_RXCSUM \
|
|
+ | NETIF_F_HW_CSUM \
|
|
+ | NETIF_F_TSO \
|
|
+ | NETIF_F_TSO6)
|
|
+
|
|
+/**
|
|
+ * struct edma_port_priv - EDMA port priv structure.
|
|
+ * @ppe_port: Pointer to PPE port
|
|
+ * @netdev: Corresponding netdevice
|
|
+ * @flags: Feature flags
|
|
+ */
|
|
+struct edma_port_priv {
|
|
+ struct ppe_port *ppe_port;
|
|
+ struct net_device *netdev;
|
|
+ unsigned long flags;
|
|
+};
|
|
+
|
|
+void edma_port_destroy(struct ppe_port *port);
|
|
+int edma_port_setup(struct ppe_port *port);
|
|
+#endif
|
|
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
|
|
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
|
|
@@ -13,6 +13,7 @@
|
|
#include <linux/regmap.h>
|
|
#include <linux/rtnetlink.h>
|
|
|
|
+#include "edma_port.h"
|
|
#include "ppe.h"
|
|
#include "ppe_port.h"
|
|
#include "ppe_regs.h"
|
|
@@ -1277,12 +1278,26 @@ int ppe_port_mac_init(struct ppe_device
|
|
goto err_port_node;
|
|
}
|
|
|
|
+ ret = edma_port_setup(&ppe_ports->port[i]);
|
|
+ if (ret) {
|
|
+ dev_err(ppe_dev->dev, "QCOM EDMA port setup failed\n");
|
|
+ i--;
|
|
+ goto err_port_setup;
|
|
+ }
|
|
+
|
|
i++;
|
|
}
|
|
|
|
of_node_put(ports_node);
|
|
return 0;
|
|
|
|
+err_port_setup:
|
|
+ /* Destroy edma ports created till now */
|
|
+ while (i >= 0) {
|
|
+ edma_port_destroy(&ppe_ports->port[i]);
|
|
+ i--;
|
|
+ }
|
|
+
|
|
err_port_clk:
|
|
for (j = 0; j < i; j++)
|
|
ppe_port_clock_deinit(&ppe_ports->port[j]);
|
|
@@ -1307,6 +1322,10 @@ void ppe_port_mac_deinit(struct ppe_devi
|
|
|
|
for (i = 0; i < ppe_dev->ports->num; i++) {
|
|
ppe_port = &ppe_dev->ports->port[i];
|
|
+
|
|
+ /* Destroy all phylinks and edma ports */
|
|
+ edma_port_destroy(ppe_port);
|
|
+
|
|
ppe_port_clock_deinit(ppe_port);
|
|
}
|
|
}
|