Only three platforms supprt MSIs, which means having all the strings and interrupt arrays always allocated wastes space. None of this data is performance critical - this data is only used when requesting and releasing the MSI interrupts. Move the MSI data out of struct stmmac_priv into its own separately allocated structure, and move its initialisation to a separate function. This removes 768 bytes from struct stmmac_priv. Link: https://lore.kernel.org/r/aYtq4ypxXTvn_Is6@shell.armlinux.org.uk Signed-off-by: Russell King (Oracle) --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 31 +++--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 96 ++++++++++++------- 2 files changed, 77 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index bba9bb9c95bf..7a66edba8f66 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -243,6 +243,23 @@ struct stmmac_est { u32 max_sdu[MTL_MAX_TX_QUEUES]; }; +struct stmmac_msi { + int sfty_ce_irq; + int sfty_ue_irq; + int rx_irq[MTL_MAX_RX_QUEUES]; + int tx_irq[MTL_MAX_TX_QUEUES]; + + /*irq name */ + char int_name_mac[IFNAMSIZ + 9]; + char int_name_wol[IFNAMSIZ + 9]; + char int_name_lpi[IFNAMSIZ + 9]; + char int_name_sfty[IFNAMSIZ + 10]; + char int_name_sfty_ce[IFNAMSIZ + 10]; + char int_name_sfty_ue[IFNAMSIZ + 10]; + char int_name_rx_irq[MTL_MAX_RX_QUEUES][IFNAMSIZ + 14]; + char int_name_tx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 18]; +}; + struct stmmac_priv { /* Frequently used values are kept adjacent for cache effect */ u32 tx_coal_frames[MTL_MAX_TX_QUEUES]; @@ -329,19 +346,7 @@ struct stmmac_priv { unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned int num_double_vlans; int sfty_irq; - int sfty_ce_irq; - int sfty_ue_irq; - int rx_irq[MTL_MAX_RX_QUEUES]; - int tx_irq[MTL_MAX_TX_QUEUES]; - /*irq name */ - char int_name_mac[IFNAMSIZ + 9]; - char int_name_wol[IFNAMSIZ + 9]; - char int_name_lpi[IFNAMSIZ + 9]; - char int_name_sfty[IFNAMSIZ + 10]; - char int_name_sfty_ce[IFNAMSIZ + 10]; - char int_name_sfty_ue[IFNAMSIZ + 10]; - char int_name_rx_irq[MTL_MAX_RX_QUEUES][IFNAMSIZ + 14]; - char int_name_tx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 18]; + struct stmmac_msi *msi; #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 11150bddd872..24de4033c886 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3725,6 +3725,7 @@ static void stmmac_free_irq(struct net_device *dev, enum request_irq_err irq_err, int irq_idx) { struct stmmac_priv *priv = netdev_priv(dev); + struct stmmac_msi *msi = priv->msi; int j; switch (irq_err) { @@ -3733,27 +3734,27 @@ static void stmmac_free_irq(struct net_device *dev, fallthrough; case REQ_IRQ_ERR_TX: for (j = irq_idx - 1; j >= 0; j--) { - if (priv->tx_irq[j] > 0) { - irq_set_affinity_hint(priv->tx_irq[j], NULL); - free_irq(priv->tx_irq[j], &priv->dma_conf.tx_queue[j]); + if (msi->tx_irq[j] > 0) { + irq_set_affinity_hint(msi->tx_irq[j], NULL); + free_irq(msi->tx_irq[j], &priv->dma_conf.tx_queue[j]); } } irq_idx = priv->plat->rx_queues_to_use; fallthrough; case REQ_IRQ_ERR_RX: for (j = irq_idx - 1; j >= 0; j--) { - if (priv->rx_irq[j] > 0) { - irq_set_affinity_hint(priv->rx_irq[j], NULL); - free_irq(priv->rx_irq[j], &priv->dma_conf.rx_queue[j]); + if (msi->rx_irq[j] > 0) { + irq_set_affinity_hint(msi->rx_irq[j], NULL); + free_irq(msi->rx_irq[j], &priv->dma_conf.rx_queue[j]); } } - if (priv->sfty_ue_irq > 0 && priv->sfty_ue_irq != dev->irq) - free_irq(priv->sfty_ue_irq, dev); + if (msi->sfty_ue_irq > 0 && msi->sfty_ue_irq != dev->irq) + free_irq(msi->sfty_ue_irq, dev); fallthrough; case REQ_IRQ_ERR_SFTY_UE: - if (priv->sfty_ce_irq > 0 && priv->sfty_ce_irq != dev->irq) - free_irq(priv->sfty_ce_irq, dev); + if (msi->sfty_ce_irq > 0 && msi->sfty_ce_irq != dev->irq) + free_irq(msi->sfty_ce_irq, dev); fallthrough; case REQ_IRQ_ERR_SFTY_CE: if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) @@ -3773,9 +3774,30 @@ static void stmmac_free_irq(struct net_device *dev, } } +static int stmmac_msi_init(struct stmmac_priv *priv, + struct stmmac_resources *res) +{ + int i; + + priv->msi = devm_kmalloc(priv->device, sizeof(*priv->msi), GFP_KERNEL); + if (!priv->msi) + return -ENOMEM; + + priv->msi->sfty_ce_irq = res->sfty_ce_irq; + priv->msi->sfty_ue_irq = res->sfty_ue_irq; + + for (i = 0; i < MTL_MAX_RX_QUEUES; i++) + priv->msi->rx_irq[i] = res->rx_irq[i]; + for (i = 0; i < MTL_MAX_TX_QUEUES; i++) + priv->msi->tx_irq[i] = res->tx_irq[i]; + + return 0; +} + static int stmmac_request_irq_multi_msi(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); + struct stmmac_msi *msi = priv->msi; enum request_irq_err irq_err; int irq_idx = 0; char *int_name; @@ -3783,7 +3805,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) int i; /* For common interrupt */ - int_name = priv->int_name_mac; + int_name = msi->int_name_mac; sprintf(int_name, "%s:%s", dev->name, "mac"); ret = request_irq(dev->irq, stmmac_mac_interrupt, 0, int_name, dev); @@ -3799,7 +3821,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) * is used for WoL */ if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) { - int_name = priv->int_name_wol; + int_name = msi->int_name_wol; sprintf(int_name, "%s:%s", dev->name, "wol"); ret = request_irq(priv->wol_irq, stmmac_mac_interrupt, @@ -3817,7 +3839,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) * Error line in case of another line is used */ if (priv->sfty_irq > 0 && priv->sfty_irq != dev->irq) { - int_name = priv->int_name_sfty; + int_name = msi->int_name_sfty; sprintf(int_name, "%s:%s", dev->name, "safety"); ret = request_irq(priv->sfty_irq, stmmac_safety_interrupt, 0, int_name, dev); @@ -3833,16 +3855,16 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) /* Request the Safety Feature Correctible Error line in * case of another line is used */ - if (priv->sfty_ce_irq > 0 && priv->sfty_ce_irq != dev->irq) { - int_name = priv->int_name_sfty_ce; + if (msi->sfty_ce_irq > 0 && msi->sfty_ce_irq != dev->irq) { + int_name = msi->int_name_sfty_ce; sprintf(int_name, "%s:%s", dev->name, "safety-ce"); - ret = request_irq(priv->sfty_ce_irq, + ret = request_irq(msi->sfty_ce_irq, stmmac_safety_interrupt, 0, int_name, dev); if (unlikely(ret < 0)) { netdev_err(priv->dev, "%s: alloc sfty ce MSI %d (error: %d)\n", - __func__, priv->sfty_ce_irq, ret); + __func__, msi->sfty_ce_irq, ret); irq_err = REQ_IRQ_ERR_SFTY_CE; goto irq_error; } @@ -3851,16 +3873,16 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) /* Request the Safety Feature Uncorrectible Error line in * case of another line is used */ - if (priv->sfty_ue_irq > 0 && priv->sfty_ue_irq != dev->irq) { - int_name = priv->int_name_sfty_ue; + if (msi->sfty_ue_irq > 0 && msi->sfty_ue_irq != dev->irq) { + int_name = msi->int_name_sfty_ue; sprintf(int_name, "%s:%s", dev->name, "safety-ue"); - ret = request_irq(priv->sfty_ue_irq, + ret = request_irq(msi->sfty_ue_irq, stmmac_safety_interrupt, 0, int_name, dev); if (unlikely(ret < 0)) { netdev_err(priv->dev, "%s: alloc sfty ue MSI %d (error: %d)\n", - __func__, priv->sfty_ue_irq, ret); + __func__, msi->sfty_ue_irq, ret); irq_err = REQ_IRQ_ERR_SFTY_UE; goto irq_error; } @@ -3870,23 +3892,23 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) for (i = 0; i < priv->plat->rx_queues_to_use; i++) { if (i >= MTL_MAX_RX_QUEUES) break; - if (priv->rx_irq[i] == 0) + if (msi->rx_irq[i] == 0) continue; - int_name = priv->int_name_rx_irq[i]; + int_name = msi->int_name_rx_irq[i]; sprintf(int_name, "%s:%s-%d", dev->name, "rx", i); - ret = request_irq(priv->rx_irq[i], + ret = request_irq(msi->rx_irq[i], stmmac_msi_intr_rx, 0, int_name, &priv->dma_conf.rx_queue[i]); if (unlikely(ret < 0)) { netdev_err(priv->dev, "%s: alloc rx-%d MSI %d (error: %d)\n", - __func__, i, priv->rx_irq[i], ret); + __func__, i, msi->rx_irq[i], ret); irq_err = REQ_IRQ_ERR_RX; irq_idx = i; goto irq_error; } - irq_set_affinity_hint(priv->rx_irq[i], + irq_set_affinity_hint(msi->rx_irq[i], cpumask_of(i % num_online_cpus())); } @@ -3894,23 +3916,23 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev) for (i = 0; i < priv->plat->tx_queues_to_use; i++) { if (i >= MTL_MAX_TX_QUEUES) break; - if (priv->tx_irq[i] == 0) + if (msi->tx_irq[i] == 0) continue; - int_name = priv->int_name_tx_irq[i]; + int_name = msi->int_name_tx_irq[i]; sprintf(int_name, "%s:%s-%d", dev->name, "tx", i); - ret = request_irq(priv->tx_irq[i], + ret = request_irq(msi->tx_irq[i], stmmac_msi_intr_tx, 0, int_name, &priv->dma_conf.tx_queue[i]); if (unlikely(ret < 0)) { netdev_err(priv->dev, "%s: alloc tx-%d MSI %d (error: %d)\n", - __func__, i, priv->tx_irq[i], ret); + __func__, i, msi->tx_irq[i], ret); irq_err = REQ_IRQ_ERR_TX; irq_idx = i; goto irq_error; } - irq_set_affinity_hint(priv->tx_irq[i], + irq_set_affinity_hint(msi->tx_irq[i], cpumask_of(i % num_online_cpus())); } @@ -7806,12 +7828,12 @@ static int __stmmac_dvr_probe(struct device *device, priv->dev->irq = res->irq; priv->wol_irq = res->wol_irq; priv->sfty_irq = res->sfty_irq; - priv->sfty_ce_irq = res->sfty_ce_irq; - priv->sfty_ue_irq = res->sfty_ue_irq; - for (i = 0; i < MTL_MAX_RX_QUEUES; i++) - priv->rx_irq[i] = res->rx_irq[i]; - for (i = 0; i < MTL_MAX_TX_QUEUES; i++) - priv->tx_irq[i] = res->tx_irq[i]; + + if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) { + ret = stmmac_msi_init(priv, res); + if (ret) + return ret; + } if (!is_zero_ether_addr(res->mac)) eth_hw_addr_set(priv->dev, res->mac); -- 2.47.3