From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c | 432 +++++++++++++++++++-----------------------------------
1 files changed, 152 insertions(+), 280 deletions(-)
diff --git a/kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c b/kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c
index b241bd9..11ec4b7 100644
--- a/kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c
+++ b/kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c
@@ -16,7 +16,6 @@
#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/tcp.h>
-#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/if_ether.h>
#include <linux/crc32.h>
@@ -45,14 +44,14 @@
#define DRIVER_NAME "rockchip_gmac_uio_drv"
#define DRIVER_VERSION "0.1"
-#define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
#define TC_DEFAULT 64
-#define DEFAULT_BUFSIZE 1536
-#define STMMAC_RX_COPYBREAK 256
-
-static int buf_sz = DEFAULT_BUFSIZE;
static int tc = TC_DEFAULT;
+
+#define DEFAULT_BUFSIZE 1536
+static int buf_sz = DEFAULT_BUFSIZE;
+
+#define STMMAC_RX_COPYBREAK 256
/**
* rockchip_gmac_uio_pdev_info
@@ -120,11 +119,11 @@
/* Free DMA regions of consistent memory previously allocated */
if (!priv->extend_desc)
- dma_free_coherent(priv->device,
- DMA_RX_SIZE * sizeof(struct dma_desc),
+ dma_free_coherent(priv->device, priv->dma_rx_size *
+ sizeof(struct dma_desc),
rx_q->dma_rx, rx_q->dma_rx_phy);
else
- dma_free_coherent(priv->device, DMA_RX_SIZE *
+ dma_free_coherent(priv->device, priv->dma_rx_size *
sizeof(struct dma_extended_desc),
rx_q->dma_erx, rx_q->dma_rx_phy);
}
@@ -142,16 +141,23 @@
/* Free TX queue resources */
for (queue = 0; queue < tx_count; queue++) {
struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
+ size_t size;
+ void *addr;
- /* Free DMA regions of consistent memory previously allocated */
- if (!priv->extend_desc)
- dma_free_coherent(priv->device,
- DMA_TX_SIZE * sizeof(struct dma_desc),
- tx_q->dma_tx, tx_q->dma_tx_phy);
- else
- dma_free_coherent(priv->device, DMA_TX_SIZE *
- sizeof(struct dma_extended_desc),
- tx_q->dma_etx, tx_q->dma_tx_phy);
+ if (priv->extend_desc) {
+ size = sizeof(struct dma_extended_desc);
+ addr = tx_q->dma_etx;
+ } else if (tx_q->tbs & STMMAC_TBS_AVAIL) {
+ size = sizeof(struct dma_edesc);
+ addr = tx_q->dma_entx;
+ } else {
+ size = sizeof(struct dma_desc);
+ addr = tx_q->dma_tx;
+ }
+
+ size *= priv->dma_tx_size;
+
+ dma_free_coherent(priv->device, size, addr, tx_q->dma_tx_phy);
}
}
@@ -173,26 +179,20 @@
for (queue = 0; queue < rx_count; queue++) {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
- rx_q->queue_index = queue;
- rx_q->priv_data = priv;
-
if (priv->extend_desc) {
- rx_q->dma_erx = dma_zalloc_coherent(priv->device,
- DMA_RX_SIZE *
- sizeof(struct
- dma_extended_desc),
- &rx_q->dma_rx_phy,
- GFP_KERNEL);
- if (!rx_q->dma_erx)
- goto err_dma;
-
- } else {
- rx_q->dma_rx = dma_zalloc_coherent(priv->device,
- DMA_RX_SIZE *
- sizeof(struct
- dma_desc),
+ rx_q->dma_erx = dma_alloc_coherent(priv->device,
+ priv->dma_rx_size *
+ sizeof(struct dma_extended_desc),
&rx_q->dma_rx_phy,
GFP_KERNEL);
+ if (!rx_q->dma_erx)
+ goto err_dma;
+ } else {
+ rx_q->dma_rx = dma_alloc_coherent(priv->device,
+ priv->dma_rx_size *
+ sizeof(struct dma_desc),
+ &rx_q->dma_rx_phy,
+ GFP_KERNEL);
if (!rx_q->dma_rx)
goto err_dma;
}
@@ -223,36 +223,38 @@
/* TX queues buffers and DMA */
for (queue = 0; queue < tx_count; queue++) {
struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
+ size_t size;
+ void *addr;
tx_q->queue_index = queue;
tx_q->priv_data = priv;
- if (priv->extend_desc) {
- tx_q->dma_etx = dma_zalloc_coherent(priv->device,
- DMA_TX_SIZE *
- sizeof(struct
- dma_extended_desc),
- &tx_q->dma_tx_phy,
- GFP_KERNEL);
- if (!tx_q->dma_etx)
- goto err_dma;
- } else {
- tx_q->dma_tx = dma_zalloc_coherent(priv->device,
- DMA_TX_SIZE *
- sizeof(struct
- dma_desc),
- &tx_q->dma_tx_phy,
- GFP_KERNEL);
- if (!tx_q->dma_tx)
- goto err_dma;
- }
+ if (priv->extend_desc)
+ size = sizeof(struct dma_extended_desc);
+ else if (tx_q->tbs & STMMAC_TBS_AVAIL)
+ size = sizeof(struct dma_edesc);
+ else
+ size = sizeof(struct dma_desc);
+
+ size *= priv->dma_tx_size;
+
+ addr = dma_alloc_coherent(priv->device, size,
+ &tx_q->dma_tx_phy, GFP_KERNEL);
+ if (!addr)
+ goto err_dma;
+
+ if (priv->extend_desc)
+ tx_q->dma_etx = addr;
+ else if (tx_q->tbs & STMMAC_TBS_AVAIL)
+ tx_q->dma_entx = addr;
+ else
+ tx_q->dma_tx = addr;
}
return 0;
err_dma:
uio_free_dma_tx_desc_resources(priv);
-
return ret;
}
@@ -291,121 +293,6 @@
}
/**
- * uio_hw_fix_mac_speed - callback for speed selection
- * @priv: driver private structure
- * Description: on some platforms (e.g. ST), some HW system configuration
- * registers have to be set according to the link speed negotiated.
- */
-static inline void uio_hw_fix_mac_speed(struct stmmac_priv *priv)
-{
- struct net_device *ndev = priv->dev;
- struct phy_device *phydev = ndev->phydev;
-
- if (likely(priv->plat->fix_mac_speed))
- priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
-}
-
-/**
- * uio_mac_flow_ctrl - Configure flow control in all queues
- * @priv: driver private structure
- * Description: It is used for configuring the flow control in all queues
- */
-static void uio_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
-{
- u32 tx_cnt = priv->plat->tx_queues_to_use;
-
- stmmac_flow_ctrl(priv, priv->hw, duplex, priv->flow_ctrl,
- priv->pause, tx_cnt);
-}
-
-/**
- * uio_adjust_link - adjusts the link parameters
- * @dev: net device structure
- * Description: this is the helper called by the physical abstraction layer
- * drivers to communicate the phy link status. According the speed and duplex
- * this driver can invoke registered glue-logic as well.
- * It also invoke the eee initialization because it could happen when switch
- * on different networks (that are eee capable).
- */
-static void uio_adjust_link(struct net_device *dev)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phydev = dev->phydev;
- bool new_state = false;
-
- if (!phydev)
- return;
-
- mutex_lock(&priv->lock);
-
- if (phydev->link) {
- u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
-
- /* Now we make sure that we can be in full duplex mode.
- * If not, we operate in half-duplex mode.
- */
- if (phydev->duplex != priv->oldduplex) {
- new_state = true;
- if (!phydev->duplex)
- ctrl &= ~priv->hw->link.duplex;
- else
- ctrl |= priv->hw->link.duplex;
- priv->oldduplex = phydev->duplex;
- }
- /* Flow Control operation */
- if (phydev->pause)
- uio_mac_flow_ctrl(priv, phydev->duplex);
-
- if (phydev->speed != priv->speed) {
- new_state = true;
- ctrl &= ~priv->hw->link.speed_mask;
- switch (phydev->speed) {
- case SPEED_1000:
- ctrl |= priv->hw->link.speed1000;
- break;
- case SPEED_100:
- ctrl |= priv->hw->link.speed100;
- break;
- case SPEED_10:
- ctrl |= priv->hw->link.speed10;
- break;
- default:
- netif_warn(priv, link, priv->dev,
- "broken speed: %d\n", phydev->speed);
- phydev->speed = SPEED_UNKNOWN;
- break;
- }
- if (phydev->speed != SPEED_UNKNOWN)
- uio_hw_fix_mac_speed(priv);
- priv->speed = phydev->speed;
- }
-
- writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
-
- if (!priv->oldlink) {
- new_state = true;
- priv->oldlink = true;
- }
- } else if (priv->oldlink) {
- new_state = true;
- priv->oldlink = false;
- priv->speed = SPEED_UNKNOWN;
- priv->oldduplex = DUPLEX_UNKNOWN;
- }
-
- if (new_state && netif_msg_link(priv))
- phy_print_status(phydev);
-
- mutex_unlock(&priv->lock);
-
- if (phydev->is_pseudo_fixed_link)
- /* Stop PHY layer to call the hook to adjust the link in case
- * of a switch is attached to the stmmac driver.
- */
- phydev->irq = PHY_IGNORE_INTERRUPT;
-}
-
-/**
* rockchip_gmac_uio_init_phy - PHY initialization
* @dev: net device structure
* Description: it initializes the driver's PHY state, and attaches the PHY
@@ -416,82 +303,38 @@
static int rockchip_gmac_uio_init_phy(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
- u32 tx_cnt = priv->plat->tx_queues_to_use;
- struct phy_device *phydev;
- char phy_id_fmt[MII_BUS_ID_SIZE + 3];
- char bus_id[MII_BUS_ID_SIZE];
- int interface = priv->plat->interface;
- int max_speed = priv->plat->max_speed;
+ struct device_node *node;
+ int ret;
- priv->oldlink = false;
- priv->speed = SPEED_UNKNOWN;
- priv->oldduplex = DUPLEX_UNKNOWN;
+ node = priv->plat->phylink_node;
- if (priv->plat->integrated_phy_power)
- priv->plat->integrated_phy_power(priv->plat->bsp_priv, true);
+ if (node)
+ ret = phylink_of_phy_connect(priv->phylink, node, 0);
- if (priv->mii)
- stmmac_mdio_reset(priv->mii);
+ /* Some DT bindings do not set-up the PHY handle. Let's try to
+ * manually parse it
+ */
+ if (!node || ret) {
+ int addr = priv->plat->phy_addr;
+ struct phy_device *phydev;
- if (priv->plat->phy_node) {
- phydev = of_phy_connect(dev, priv->plat->phy_node,
- &uio_adjust_link, 0, interface);
- } else {
- snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
- priv->plat->bus_id);
-
- snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
- priv->plat->phy_addr);
- netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__,
- phy_id_fmt);
-
- phydev = phy_connect(dev, phy_id_fmt, &uio_adjust_link,
- interface);
- }
-
- if (IS_ERR_OR_NULL(phydev)) {
- netdev_err(priv->dev, "Could not attach to PHY\n");
- if (!phydev)
+ phydev = mdiobus_get_phy(priv->mii, addr);
+ if (!phydev) {
+ netdev_err(priv->dev, "no phy at addr %d\n", addr);
return -ENODEV;
+ }
- return PTR_ERR(phydev);
+ ret = phylink_connect_phy(priv->phylink, phydev);
}
- /* Stop Advertising 1000BASE Capability if interface is not GMII */
- if (interface == PHY_INTERFACE_MODE_MII ||
- interface == PHY_INTERFACE_MODE_RMII ||
- (max_speed < 1000 && max_speed > 0))
- phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full);
+ if (!priv->plat->pmt) {
+ struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
- /* Half-duplex mode not supported with multiqueue
- * half-duplex can only works with single queue
- */
- if (tx_cnt > 1)
- phydev->supported &= ~(SUPPORTED_1000baseT_Half |
- SUPPORTED_100baseT_Half |
- SUPPORTED_10baseT_Half);
-
- /* Broken HW is sometimes missing the pull-up resistor on the
- * MDIO line, which results in reads to non-existent devices returning
- * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
- * device as well.
- * Note: phydev->phy_id is the result of reading the UID PHY registers.
- */
- if (!priv->plat->phy_node && phydev->phy_id == 0) {
- phy_disconnect(phydev);
- return -ENODEV;
+ phylink_ethtool_get_wol(priv->phylink, &wol);
+ device_set_wakeup_capable(priv->device, !!wol.supported);
}
- /* uio_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid
- * subsequent PHY polling, make sure we force a link transition if
- * we have a UP/DOWN/UP transition
- */
- if (phydev->is_pseudo_fixed_link)
- phydev->irq = PHY_POLL;
-
- phy_attached_info(phydev);
- return 0;
+ return ret;
}
/**
@@ -545,7 +388,8 @@
rx_q->dma_rx_phy, chan);
rx_q->rx_tail_addr = rx_q->dma_rx_phy +
- (DMA_RX_SIZE * sizeof(struct dma_desc));
+ (priv->dma_rx_size *
+ sizeof(struct dma_desc));
stmmac_set_rx_tail_ptr(priv, priv->ioaddr,
rx_q->rx_tail_addr, chan);
}
@@ -574,12 +418,12 @@
/* set TX ring length */
for (chan = 0; chan < tx_channels_count; chan++)
stmmac_set_tx_ring_len(priv, priv->ioaddr,
- (DMA_TX_SIZE - 1), chan);
+ (priv->dma_tx_size - 1), chan);
/* set RX ring length */
for (chan = 0; chan < rx_channels_count; chan++)
stmmac_set_rx_ring_len(priv, priv->ioaddr,
- (DMA_RX_SIZE - 1), chan);
+ (priv->dma_rx_size - 1), chan);
}
/**
@@ -617,11 +461,11 @@
continue;
stmmac_config_cbs(priv, priv->hw,
- priv->plat->tx_queues_cfg[queue].send_slope,
- priv->plat->tx_queues_cfg[queue].idle_slope,
- priv->plat->tx_queues_cfg[queue].high_credit,
- priv->plat->tx_queues_cfg[queue].low_credit,
- queue);
+ priv->plat->tx_queues_cfg[queue].send_slope,
+ priv->plat->tx_queues_cfg[queue].idle_slope,
+ priv->plat->tx_queues_cfg[queue].high_credit,
+ priv->plat->tx_queues_cfg[queue].low_credit,
+ queue);
}
}
@@ -703,6 +547,22 @@
}
}
+static void uio_mac_config_rss(struct stmmac_priv *priv)
+{
+ if (!priv->dma_cap.rssen || !priv->plat->rss_en) {
+ priv->rss.enable = false;
+ return;
+ }
+
+ if (priv->dev->features & NETIF_F_RXHASH)
+ priv->rss.enable = true;
+ else
+ priv->rss.enable = false;
+
+ stmmac_rss_configure(priv, priv->hw, &priv->rss,
+ priv->plat->rx_queues_to_use);
+}
+
/**
* uio_mac_enable_rx_queues - Enable MAC rx queues
* @priv: driver private structure
@@ -764,14 +624,17 @@
/* Set RX routing */
if (rx_queues_count > 1)
uio_mac_config_rx_queues_routing(priv);
+
+ /* Receive Side Scaling */
+ if (rx_queues_count > 1)
+ uio_mac_config_rss(priv);
}
static void uio_safety_feat_configuration(struct stmmac_priv *priv)
{
if (priv->dma_cap.asp) {
netdev_info(priv->dev, "Enabling Safety Features\n");
- stmmac_safety_feat_config(priv, priv->ioaddr,
- priv->dma_cap.asp);
+ stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp);
} else {
netdev_info(priv->dev, "No Safety Features support found\n");
}
@@ -840,26 +703,6 @@
}
/**
- * rockchip_gmac_uio_mmc_setup: setup the Mac Management Counters (MMC)
- * @priv: driver private structure
- * Description: this masks the MMC irq, in fact, the counters are managed in SW.
- */
-static void rockchip_gmac_uio_mmc_setup(struct stmmac_priv *priv)
-{
- unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
- MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
-
- dwmac_mmc_intr_all_mask(priv->mmcaddr);
-
- if (priv->dma_cap.rmon) {
- dwmac_mmc_ctrl(priv->mmcaddr, mode);
- memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
- } else {
- netdev_info(priv->dev, "No MAC Management Counters available\n");
- }
-}
-
-/**
* rockchip_gmac_uio_hw_setup - setup mac in a usable state.
* @dev : pointer to the device structure.
* @init_ptp: initialize PTP if set
@@ -923,13 +766,29 @@
/* Set the HW DMA mode and the COE */
uio_dma_operation_mode(priv);
- rockchip_gmac_uio_mmc_setup(priv);
-
if (priv->hw->pcs)
stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0);
/* set TX and RX rings length */
uio_set_rings_length(priv);
+
+ return 0;
+}
+
+static int uio_set_bfsize(int mtu, int bufsize)
+{
+ int ret = bufsize;
+
+ if (mtu >= BUF_SIZE_8KiB)
+ ret = BUF_SIZE_16KiB;
+ else if (mtu >= BUF_SIZE_4KiB)
+ ret = BUF_SIZE_8KiB;
+ else if (mtu >= BUF_SIZE_2KiB)
+ ret = BUF_SIZE_4KiB;
+ else if (mtu > DEFAULT_BUFSIZE)
+ ret = BUF_SIZE_2KiB;
+ else
+ ret = DEFAULT_BUFSIZE;
return ret;
}
@@ -946,11 +805,12 @@
static int uio_open(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ int bfsize = 0;
int ret;
- if (priv->hw->pcs != STMMAC_PCS_RGMII &&
- priv->hw->pcs != STMMAC_PCS_TBI &&
- priv->hw->pcs != STMMAC_PCS_RTBI) {
+ if (priv->hw->pcs != STMMAC_PCS_TBI &&
+ priv->hw->pcs != STMMAC_PCS_RTBI &&
+ !priv->hw->xpcs) {
ret = rockchip_gmac_uio_init_phy(dev);
if (ret) {
netdev_err(priv->dev,
@@ -961,11 +821,24 @@
}
/* Extra statistics */
- memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
priv->xstats.threshold = tc;
- priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
+ bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu);
+ if (bfsize < 0)
+ bfsize = 0;
+
+ if (bfsize < BUF_SIZE_16KiB)
+ bfsize = uio_set_bfsize(dev->mtu, priv->dma_buf_sz);
+
+ priv->dma_buf_sz = bfsize;
+ buf_sz = bfsize;
+
priv->rx_copybreak = STMMAC_RX_COPYBREAK;
+
+ if (!priv->dma_tx_size)
+ priv->dma_tx_size = DMA_DEFAULT_TX_SIZE;
+ if (!priv->dma_rx_size)
+ priv->dma_rx_size = DMA_DEFAULT_RX_SIZE;
ret = uio_alloc_dma_desc_resources(priv);
if (ret < 0) {
@@ -980,16 +853,16 @@
goto init_error;
}
- if (dev->phydev)
- phy_start(dev->phydev);
+ phylink_start(priv->phylink);
+ /* We may have called phylink_speed_down before */
+ phylink_speed_up(priv->phylink);
return 0;
init_error:
uio_free_dma_desc_resources(priv);
dma_desc_error:
- if (dev->phydev)
- phy_disconnect(dev->phydev);
+ phylink_disconnect_phy(priv->phylink);
return ret;
}
@@ -1091,12 +964,12 @@
uio->mem[1].name = "eth_rx_bd";
uio->mem[1].addr = priv->rx_queue[0].dma_rx_phy;
- uio->mem[1].size = DMA_RX_SIZE * sizeof(struct dma_desc);
+ uio->mem[1].size = priv->dma_rx_size * sizeof(struct dma_desc);
uio->mem[1].memtype = UIO_MEM_PHYS;
uio->mem[2].name = "eth_tx_bd";
uio->mem[2].addr = priv->tx_queue[0].dma_tx_phy;
- uio->mem[2].size = DMA_TX_SIZE * sizeof(struct dma_desc);
+ uio->mem[2].size = priv->dma_tx_size * sizeof(struct dma_desc);
uio->mem[2].memtype = UIO_MEM_PHYS;
uio->open = rockchip_gmac_uio_open;
@@ -1148,7 +1021,7 @@
if (netdev) {
rtnl_lock();
- dev_open(netdev);
+ dev_open(netdev, NULL);
rtnl_unlock();
}
@@ -1175,4 +1048,3 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ROCKCHIP");
MODULE_DESCRIPTION("ROCKCHIP GMAC UIO Driver");
-
--
Gitblit v1.6.2