Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +18 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2018-19, Linaro Limited // Copyright (c) 2018-20, Linaro Limited #include <linux/module.h> #include <linux/of.h> Loading Loading @@ -1287,6 +1287,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->ipa_enabled = true; priv->rx_queue[IPA_DMA_RX_CH].skip_sw = true; priv->tx_queue[IPA_DMA_TX_CH].skip_sw = true; ethqos_ipa_offload_event_handler(ethqos, EV_PROBE_INIT); #endif return ret; Loading Loading @@ -1328,7 +1329,9 @@ static int qcom_ethqos_suspend(struct device *dev) struct qcom_ethqos *ethqos; struct net_device *ndev = NULL; int ret; int allow_suspend = 0; ETHQOSDBG("Suspend Enter\n"); if (of_device_is_compatible(dev->of_node, "qcom,emac-smmu-embedded")) { ETHQOSDBG("smmu return\n"); return 0; Loading @@ -1340,6 +1343,12 @@ static int qcom_ethqos_suspend(struct device *dev) ndev = dev_get_drvdata(dev); ethqos_ipa_offload_event_handler(&allow_suspend, EV_DPM_SUSPEND); if (!allow_suspend) { enable_irq_wake(ndev->irq); ETHQOSDBG("Suspend Exit enable IRQ\n"); return 0; } if (!ndev || !netif_running(ndev)) return -EINVAL; Loading Loading @@ -1372,10 +1381,18 @@ static int qcom_ethqos_resume(struct device *dev) return -EINVAL; } if (!ethqos->clks_suspended) { disable_irq_wake(ndev->irq); ETHQOSDBG("Resume Exit disable IRQ\n"); return 0; } qcom_ethqos_phy_resume_clks(ethqos, ndev); ret = stmmac_resume(dev); ethqos_ipa_offload_event_handler(NULL, EV_DPM_RESUME); ETHQOSDBG("<--Resume Exit\n"); return ret; } Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa-offload.h +17 −16 Original line number Diff line number Diff line /* Copyright (c) 2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -35,21 +35,6 @@ buf1[QTAG_ETH_TYPE_OFFSET + 1]));\ } while (0) enum IPA_OFFLOAD_EVENT { EV_INVALID = 0, EV_DEV_OPEN = 1, EV_DEV_CLOSE = 2, EV_IPA_READY = 3, EV_IPA_UC_READY = 4, EV_PHY_LINK_UP = 5, EV_PHY_LINK_DOWN = 6, EV_DPM_SUSPEND = 7, EV_DPM_RESUME = 8, EV_USR_SUSPEND = 9, EV_USR_RESUME = 10, EV_IPA_OFFLOAD_MAX = 11, EV_IPA_OFFLOAD_REMOVE = 12, }; #ifdef CONFIG_ETH_IPA_OFFLOAD void ethqos_ipa_offload_event_handler(void *data, int ev); Loading @@ -59,4 +44,20 @@ static inline void ethqos_ipa_offload_event_handler(void *data, int ev) } #endif #define EV_INVALID 0 #define EV_PROBE_INIT (EV_INVALID + 1) #define EV_IPA_ENABLED (EV_PROBE_INIT + 1) #define EV_DEV_OPEN (EV_IPA_ENABLED + 1) #define EV_DEV_CLOSE (EV_DEV_OPEN + 1) #define EV_IPA_READY (EV_DEV_CLOSE + 1) #define EV_IPA_UC_READY (EV_IPA_READY + 1) #define EV_PHY_LINK_UP (EV_IPA_UC_READY + 1) #define EV_PHY_LINK_DOWN (EV_PHY_LINK_UP + 1) #define EV_DPM_SUSPEND (EV_PHY_LINK_DOWN + 1) #define EV_DPM_RESUME (EV_DPM_SUSPEND + 1) #define EV_USR_SUSPEND (EV_DPM_RESUME + 1) #define EV_USR_RESUME (EV_USR_SUSPEND + 1) #define EV_IPA_OFFLOAD_REMOVE (EV_USR_RESUME + 1) #define EV_IPA_OFFLOAD_MAX (EV_IPA_OFFLOAD_REMOVE + 1) #endif drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa.c +122 −107 Original line number Diff line number Diff line Loading @@ -995,7 +995,7 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) { struct qcom_ethqos *ethqos = eth_ipa_ctx.ethqos; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct sk_buff *skb = (struct sk_buff *)data; struct iphdr *iph = NULL; int stat = NET_RX_SUCCESS; Loading @@ -1007,14 +1007,14 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, return; } if (!ntn_ipa) { ETHQOSERR("Null Param ntn_ipa %pK\n", ntn_ipa); if (!eth_ipa) { ETHQOSERR("Null Param eth_ipa %pK\n", eth_ipa); return; } if (!ntn_ipa->ipa_offload_conn) { if (!eth_ipa->ipa_offload_conn) { ETHQOSERR("ipa_cb before offload is ready %d\n", ntn_ipa->ipa_offload_conn); eth_ipa->ipa_offload_conn); return; } Loading Loading @@ -1065,7 +1065,7 @@ static int ethqos_ipa_offload_init(struct qcom_ethqos *pdata) { struct ipa_uc_offload_intf_params in; struct ipa_uc_offload_out_params out; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct ethhdr eth_l2_hdr_v4; struct ethhdr eth_l2_hdr_v6; #ifdef ETHQOS_IPA_OFFLOAD_VLAN Loading Loading @@ -1145,9 +1145,9 @@ static int ethqos_ipa_offload_init(struct qcom_ethqos *pdata) ret = -1; return ret; } ntn_ipa->ipa_client_hndl = out.clnt_hndl; eth_ipa->ipa_client_hndl = out.clnt_hndl; ETHQOSDBG("Recevied IPA Offload Client Handle %d", ntn_ipa->ipa_client_hndl); eth_ipa->ipa_client_hndl); pdata->ipa_enabled = true; return 0; Loading @@ -1155,7 +1155,7 @@ static int ethqos_ipa_offload_init(struct qcom_ethqos *pdata) static int ethqos_ipa_offload_cleanup(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; int ret = 0; ETHQOSDBG("begin\n"); Loading @@ -1165,12 +1165,12 @@ static int ethqos_ipa_offload_cleanup(struct qcom_ethqos *ethqos) return -ENOMEM; } if (!ntn_ipa->ipa_client_hndl) { if (!eth_ipa->ipa_client_hndl) { ETHQOSERR("cleanup called with NULL IPA client handle\n"); return -ENOMEM; } ret = ipa_uc_offload_cleanup(ntn_ipa->ipa_client_hndl); ret = ipa_uc_offload_cleanup(eth_ipa->ipa_client_hndl); if (ret) { ETHQOSERR("Could not cleanup IPA Offload ret %d\n", ret); ret = -1; Loading @@ -1183,14 +1183,23 @@ static int ethqos_ipa_offload_cleanup(struct qcom_ethqos *ethqos) return ret; } static bool ethqos_is_phy_link_up(struct stmmac_priv *priv) static inline void *ethqos_get_priv(struct qcom_ethqos *ethqos) { struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); return priv; } static bool ethqos_is_phy_link_up(struct qcom_ethqos *ethqos) { /* PHY driver initializes phydev->link=1. * So, phydev->link is 1 even on booup with no PHY connected. * phydev->link is valid only after adjust_link is called once. * Use (pdata->oldlink != -1) to indicate phy link is not up */ struct qcom_ethqos *ethqos = priv->plat->bsp_priv; struct stmmac_priv *priv = ethqos_get_priv(ethqos); return ethqos->always_on_phy ? 1 : ((priv->oldlink != -1) && priv->dev->phydev && priv->dev->phydev->link); Loading @@ -1202,11 +1211,8 @@ static ssize_t read_ipa_offload_status(struct file *file, { unsigned int len = 0, buf_len = NTN_IPA_DBG_MAX_MSG_LEN; struct qcom_ethqos *ethqos = file->private_data; struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); if (ethqos_is_phy_link_up(priv)) { if (ethqos_is_phy_link_up(ethqos)) { if (eth_ipa_ctx.ipa_offload_susp) len += scnprintf(buf + len, buf_len - len, "IPA Offload suspended\n"); Loading Loading @@ -1259,7 +1265,7 @@ static ssize_t suspend_resume_ipa_offload(struct file *file, if (kstrtos8(in_buf, 0, &option)) return -EFAULT; if (ethqos_is_phy_link_up(priv)) { if (ethqos_is_phy_link_up(ethqos)) { if (option == 1) ethqos_ipa_offload_event_handler(priv, EV_USR_SUSPEND); else if (option == 0) Loading @@ -1276,12 +1282,12 @@ static ssize_t read_ipa_stats(struct file *file, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; char *buf; unsigned int len = 0, buf_len = 2000; ssize_t ret_cnt; if (!ethqos || !ntn_ipa) { if (!ethqos || !eth_ipa) { ETHQOSERR("NULL Pointer\n"); return -EINVAL; } Loading Loading @@ -1410,7 +1416,7 @@ static ssize_t read_ntn_dma_stats(struct file *file, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct ethqos_ipa_stats *dma_stats = ð_ipa_ctx.ipa_stats; char *buf; unsigned int len = 0, buf_len = 3000; Loading Loading @@ -1446,7 +1452,7 @@ static ssize_t read_ntn_dma_stats(struct file *file, "RX Tail Pointer Index: ", dma_stats->ipa_rx_tail_ptr_indx); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", "RX Doorbell Address: ", ntn_ipa->uc_db_rx_addr); "RX Doorbell Address: ", eth_ipa->uc_db_rx_addr); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", Loading Loading @@ -1501,7 +1507,7 @@ static ssize_t read_ntn_dma_stats(struct file *file, len += scnprintf(buf + len, buf_len - len, "%-50s %10lu\n", "TX Tail Pointer Index: ", dma_stats->ipa_tx_tail_ptr_indx); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", "TX Doorbell Address: ", ntn_ipa->uc_db_tx_addr); "TX Doorbell Address: ", eth_ipa->uc_db_tx_addr); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", Loading Loading @@ -1577,22 +1583,22 @@ static const struct file_operations fops_ntn_ipa_offload_en = { static int ethqos_ipa_cleanup_debugfs(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; if (!ethqos || !ntn_ipa) { if (!ethqos || !eth_ipa) { ETHQOSERR("Null Param\n"); return -ENOMEM; } if (ethqos->debugfs_dir) { debugfs_remove(ntn_ipa->debugfs_ipa_stats); ntn_ipa->debugfs_ipa_stats = NULL; debugfs_remove(eth_ipa->debugfs_ipa_stats); eth_ipa->debugfs_ipa_stats = NULL; debugfs_remove(ntn_ipa->debugfs_dma_stats); ntn_ipa->debugfs_dma_stats = NULL; debugfs_remove(eth_ipa->debugfs_dma_stats); eth_ipa->debugfs_dma_stats = NULL; debugfs_remove(ntn_ipa->debugfs_suspend_ipa_offload); ntn_ipa->debugfs_suspend_ipa_offload = NULL; debugfs_remove(eth_ipa->debugfs_suspend_ipa_offload); eth_ipa->debugfs_suspend_ipa_offload = NULL; } ETHQOSDBG("IPA debugfs Deleted Successfully\n"); Loading @@ -1608,38 +1614,38 @@ static int ethqos_ipa_cleanup_debugfs(struct qcom_ethqos *ethqos) */ static int ethqos_ipa_create_debugfs(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; ntn_ipa->debugfs_suspend_ipa_offload = eth_ipa->debugfs_suspend_ipa_offload = debugfs_create_file("suspend_ipa_offload", 0600, ethqos->debugfs_dir, ethqos, &fops_ntn_ipa_offload_en); if (!ntn_ipa->debugfs_suspend_ipa_offload || IS_ERR(ntn_ipa->debugfs_suspend_ipa_offload)) { if (!eth_ipa->debugfs_suspend_ipa_offload || IS_ERR(eth_ipa->debugfs_suspend_ipa_offload)) { ETHQOSERR("Cannot create debugfs ipa_offload_en %d\n", (int)ntn_ipa->debugfs_suspend_ipa_offload); (int)eth_ipa->debugfs_suspend_ipa_offload); goto fail; } ntn_ipa->debugfs_ipa_stats = eth_ipa->debugfs_ipa_stats = debugfs_create_file("ipa_stats", 0600, ethqos->debugfs_dir, ethqos, &fops_ipa_stats); if (!ntn_ipa->debugfs_ipa_stats || IS_ERR(ntn_ipa->debugfs_ipa_stats)) { if (!eth_ipa->debugfs_ipa_stats || IS_ERR(eth_ipa->debugfs_ipa_stats)) { ETHQOSERR("Cannot create debugfs_ipa_stats %d\n", (int)ntn_ipa->debugfs_ipa_stats); (int)eth_ipa->debugfs_ipa_stats); goto fail; } ntn_ipa->debugfs_dma_stats = eth_ipa->debugfs_dma_stats = debugfs_create_file("dma_stats", 0600, ethqos->debugfs_dir, ethqos, &fops_ntn_dma_stats); if (!ntn_ipa->debugfs_suspend_ipa_offload || IS_ERR(ntn_ipa->debugfs_suspend_ipa_offload)) { if (!eth_ipa->debugfs_suspend_ipa_offload || IS_ERR(eth_ipa->debugfs_suspend_ipa_offload)) { ETHQOSERR("Cannot create debugfs_dma_stats %d\n", (int)ntn_ipa->debugfs_dma_stats); (int)eth_ipa->debugfs_dma_stats); goto fail; } Loading @@ -1652,7 +1658,7 @@ static int ethqos_ipa_create_debugfs(struct qcom_ethqos *ethqos) static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct ipa_uc_offload_conn_in_params in; struct ipa_uc_offload_conn_out_params out; struct ipa_ntn_setup_info rx_setup_info = {0}; Loading @@ -1678,7 +1684,7 @@ static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) memset(&out, 0, sizeof(out)); memset(&profile, 0, sizeof(profile)); in.clnt_hndl = ntn_ipa->ipa_client_hndl; in.clnt_hndl = eth_ipa->ipa_client_hndl; /* Uplink Setup */ if (emac_emb_smmu_ctx.valid) Loading Loading @@ -1798,8 +1804,8 @@ static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) goto mem_free; } ntn_ipa->uc_db_rx_addr = out.u.ntn.ul_uc_db_pa; ntn_ipa->uc_db_tx_addr = out.u.ntn.dl_uc_db_pa; eth_ipa->uc_db_rx_addr = out.u.ntn.ul_uc_db_pa; eth_ipa->uc_db_tx_addr = out.u.ntn.dl_uc_db_pa; /* Set Perf Profile For PROD/CONS Pipes */ profile.max_supported_bw_mbps = ethqos->speed; Loading Loading @@ -1857,7 +1863,7 @@ static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) static int ethqos_ipa_offload_disconnect(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; int ret = 0; ETHQOSDBG("- begin\n"); Loading @@ -1867,7 +1873,7 @@ static int ethqos_ipa_offload_disconnect(struct qcom_ethqos *ethqos) return -ENOMEM; } ret = ipa_uc_offload_disconn_pipes(ntn_ipa->ipa_client_hndl); ret = ipa_uc_offload_disconn_pipes(eth_ipa->ipa_client_hndl); if (ret) { ETHQOSERR("Could not cleanup IPA Offload ret %d\n", ret); return ret; Loading Loading @@ -2129,7 +2135,7 @@ static void ethqos_ipaucrdy_wq(struct work_struct *work) static void ethqos_ipa_uc_ready_cb(void *user_data) { struct qcom_ethqos *pdata = (struct qcom_ethqos *)user_data; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; if (!pdata) { ETHQOSERR("Null Param pdata %pK\n", pdata); Loading @@ -2137,8 +2143,8 @@ static void ethqos_ipa_uc_ready_cb(void *user_data) } ETHQOSDBG("Received IPA UC ready callback\n"); INIT_WORK(&ntn_ipa->ntn_ipa_rdy_work, ethqos_ipaucrdy_wq); queue_work(system_unbound_wq, &ntn_ipa->ntn_ipa_rdy_work); INIT_WORK(ð_ipa->ntn_ipa_rdy_work, ethqos_ipaucrdy_wq); queue_work(system_unbound_wq, ð_ipa->ntn_ipa_rdy_work); } static int ethqos_ipa_uc_ready(struct qcom_ethqos *pdata) Loading @@ -2165,10 +2171,14 @@ static int ethqos_ipa_uc_ready(struct qcom_ethqos *pdata) void ethqos_ipa_offload_event_handler(void *data, int ev) { struct stmmac_priv *priv = data; struct qcom_ethqos *pdata = priv->plat->bsp_priv; ETHQOSDBG("Enter: event=%d\n", ev); if (ev == EV_PROBE_INIT) { eth_ipa_ctx.ethqos = data; mutex_init(ð_ipa_ctx.ipa_lock); return; } IPA_LOCK(); switch (ev) { Loading @@ -2181,7 +2191,7 @@ void ethqos_ipa_offload_event_handler(void *data, !eth_ipa_ctx.ipa_offload_conn) break; if (!ethqos_ipa_offload_suspend(pdata)) if (!ethqos_ipa_offload_suspend(eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_link_down = true; } break; Loading @@ -2194,43 +2204,39 @@ void ethqos_ipa_offload_event_handler(void *data, /* Link up event is expected only after link down */ if (eth_ipa_ctx.ipa_offload_link_down) { ethqos_ipa_offload_resume(pdata); ethqos_ipa_offload_resume(eth_ipa_ctx.ethqos); } else if (eth_ipa_ctx.emac_dev_ready && eth_ipa_ctx.ipa_uc_ready) { ethqos_enable_ipa_offload(pdata); ethqos_enable_ipa_offload(eth_ipa_ctx.ethqos); } eth_ipa_ctx.ipa_offload_link_down = false; } break; case EV_DEV_OPEN: { eth_ipa_ctx.ethqos = pdata; ethqos_ipa_config_queues(pdata); ethqos_ipa_config_queues(eth_ipa_ctx.ethqos); eth_ipa_ctx.emac_dev_ready = true; if (!eth_ipa_ctx.ipa_ready) ethqos_ipa_ready(pdata); ethqos_ipa_ready(eth_ipa_ctx.ethqos); if (!eth_ipa_ctx.ipa_uc_ready) ethqos_ipa_uc_ready(pdata); ethqos_ipa_uc_ready(eth_ipa_ctx.ethqos); } break; case EV_IPA_READY: { eth_ipa_ctx.ipa_ready = true; if (!eth_ipa_ctx.ipa_uc_ready) ethqos_ipa_uc_ready(pdata); ethqos_ipa_uc_ready(eth_ipa_ctx.ethqos); if (eth_ipa_ctx.ipa_uc_ready && ethqos_is_phy_link_up(priv)) ethqos_enable_ipa_offload(pdata); ethqos_is_phy_link_up(eth_ipa_ctx.ethqos)) ethqos_enable_ipa_offload(eth_ipa_ctx.ethqos); } break; case EV_IPA_UC_READY: { eth_ipa_ctx.ipa_uc_ready = true; Loading @@ -2240,16 +2246,16 @@ void ethqos_ipa_offload_event_handler(void *data, break; if (eth_ipa_ctx.ipa_ready) { if (!eth_ipa_ctx.ipa_offload_init) { if (!ethqos_ipa_offload_init(pdata)) if (!ethqos_ipa_offload_init( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_init = true; } } if (ethqos_is_phy_link_up(priv)) ethqos_enable_ipa_offload(pdata); if (ethqos_is_phy_link_up(eth_ipa_ctx.ethqos)) ethqos_enable_ipa_offload(eth_ipa_ctx.ethqos); } break; case EV_DEV_CLOSE: { eth_ipa_ctx.emac_dev_ready = false; Loading @@ -2257,27 +2263,35 @@ void ethqos_ipa_offload_event_handler(void *data, if (eth_ipa_ctx.ipa_uc_ready) ipa_uc_offload_dereg_rdyCB(IPA_UC_NTN); ethqos_disable_ipa_offload(pdata); ethqos_disable_ipa_offload(eth_ipa_ctx.ethqos); /* reset link down on dev close */ eth_ipa_ctx.ipa_offload_link_down = 0; } break; case EV_DPM_SUSPEND: { if (eth_ipa_ctx.ipa_offload_conn) *(int *)data = false; else *(int *)data = true; } break; case EV_USR_SUSPEND: { if (!eth_ipa_ctx.ipa_offload_susp && !eth_ipa_ctx.ipa_offload_link_down) if (!ethqos_ipa_offload_suspend(pdata)) eth_ipa_ctx.ipa_offload_susp = true; if (!ethqos_ipa_offload_suspend( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_susp = true; } break; case EV_DPM_RESUME: { if (eth_ipa_ctx.ipa_offload_susp) { if (ethqos_is_phy_link_up(priv)) { if (!ethqos_ipa_offload_resume(pdata)) if (ethqos_is_phy_link_up(eth_ipa_ctx.ethqos)) { if (!ethqos_ipa_offload_resume( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_susp = false; } else { Loading @@ -2294,24 +2308,25 @@ void ethqos_ipa_offload_event_handler(void *data, = true; } } } break; case EV_USR_RESUME: { if (eth_ipa_ctx.ipa_offload_susp) { if (!ethqos_ipa_offload_resume(pdata)) eth_ipa_ctx.ipa_offload_susp = false; if (!ethqos_ipa_offload_resume( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_susp = false; } } break; case EV_IPA_OFFLOAD_REMOVE: { ethqos_rx_buf_free_mem(pdata, IPA_DMA_RX_CH); ethqos_tx_buf_free_mem(pdata, IPA_DMA_TX_CH); ethqos_rx_desc_free_mem(pdata, IPA_DMA_RX_CH); ethqos_tx_desc_free_mem(pdata, IPA_DMA_TX_CH); ethqos_free_ipa_rx_queue_struct(pdata); ethqos_free_ipa_tx_queue_struct(pdata); ethqos_rx_buf_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_RX_CH); ethqos_tx_buf_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_TX_CH); ethqos_rx_desc_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_RX_CH); ethqos_tx_desc_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_TX_CH); ethqos_free_ipa_rx_queue_struct(eth_ipa_ctx.ethqos); ethqos_free_ipa_tx_queue_struct(eth_ipa_ctx.ethqos); } break; case EV_INVALID: Loading Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +18 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2018-19, Linaro Limited // Copyright (c) 2018-20, Linaro Limited #include <linux/module.h> #include <linux/of.h> Loading Loading @@ -1287,6 +1287,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->ipa_enabled = true; priv->rx_queue[IPA_DMA_RX_CH].skip_sw = true; priv->tx_queue[IPA_DMA_TX_CH].skip_sw = true; ethqos_ipa_offload_event_handler(ethqos, EV_PROBE_INIT); #endif return ret; Loading Loading @@ -1328,7 +1329,9 @@ static int qcom_ethqos_suspend(struct device *dev) struct qcom_ethqos *ethqos; struct net_device *ndev = NULL; int ret; int allow_suspend = 0; ETHQOSDBG("Suspend Enter\n"); if (of_device_is_compatible(dev->of_node, "qcom,emac-smmu-embedded")) { ETHQOSDBG("smmu return\n"); return 0; Loading @@ -1340,6 +1343,12 @@ static int qcom_ethqos_suspend(struct device *dev) ndev = dev_get_drvdata(dev); ethqos_ipa_offload_event_handler(&allow_suspend, EV_DPM_SUSPEND); if (!allow_suspend) { enable_irq_wake(ndev->irq); ETHQOSDBG("Suspend Exit enable IRQ\n"); return 0; } if (!ndev || !netif_running(ndev)) return -EINVAL; Loading Loading @@ -1372,10 +1381,18 @@ static int qcom_ethqos_resume(struct device *dev) return -EINVAL; } if (!ethqos->clks_suspended) { disable_irq_wake(ndev->irq); ETHQOSDBG("Resume Exit disable IRQ\n"); return 0; } qcom_ethqos_phy_resume_clks(ethqos, ndev); ret = stmmac_resume(dev); ethqos_ipa_offload_event_handler(NULL, EV_DPM_RESUME); ETHQOSDBG("<--Resume Exit\n"); return ret; } Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa-offload.h +17 −16 Original line number Diff line number Diff line /* Copyright (c) 2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -35,21 +35,6 @@ buf1[QTAG_ETH_TYPE_OFFSET + 1]));\ } while (0) enum IPA_OFFLOAD_EVENT { EV_INVALID = 0, EV_DEV_OPEN = 1, EV_DEV_CLOSE = 2, EV_IPA_READY = 3, EV_IPA_UC_READY = 4, EV_PHY_LINK_UP = 5, EV_PHY_LINK_DOWN = 6, EV_DPM_SUSPEND = 7, EV_DPM_RESUME = 8, EV_USR_SUSPEND = 9, EV_USR_RESUME = 10, EV_IPA_OFFLOAD_MAX = 11, EV_IPA_OFFLOAD_REMOVE = 12, }; #ifdef CONFIG_ETH_IPA_OFFLOAD void ethqos_ipa_offload_event_handler(void *data, int ev); Loading @@ -59,4 +44,20 @@ static inline void ethqos_ipa_offload_event_handler(void *data, int ev) } #endif #define EV_INVALID 0 #define EV_PROBE_INIT (EV_INVALID + 1) #define EV_IPA_ENABLED (EV_PROBE_INIT + 1) #define EV_DEV_OPEN (EV_IPA_ENABLED + 1) #define EV_DEV_CLOSE (EV_DEV_OPEN + 1) #define EV_IPA_READY (EV_DEV_CLOSE + 1) #define EV_IPA_UC_READY (EV_IPA_READY + 1) #define EV_PHY_LINK_UP (EV_IPA_UC_READY + 1) #define EV_PHY_LINK_DOWN (EV_PHY_LINK_UP + 1) #define EV_DPM_SUSPEND (EV_PHY_LINK_DOWN + 1) #define EV_DPM_RESUME (EV_DPM_SUSPEND + 1) #define EV_USR_SUSPEND (EV_DPM_RESUME + 1) #define EV_USR_RESUME (EV_USR_SUSPEND + 1) #define EV_IPA_OFFLOAD_REMOVE (EV_USR_RESUME + 1) #define EV_IPA_OFFLOAD_MAX (EV_IPA_OFFLOAD_REMOVE + 1) #endif
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa.c +122 −107 Original line number Diff line number Diff line Loading @@ -995,7 +995,7 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data) { struct qcom_ethqos *ethqos = eth_ipa_ctx.ethqos; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct sk_buff *skb = (struct sk_buff *)data; struct iphdr *iph = NULL; int stat = NET_RX_SUCCESS; Loading @@ -1007,14 +1007,14 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, return; } if (!ntn_ipa) { ETHQOSERR("Null Param ntn_ipa %pK\n", ntn_ipa); if (!eth_ipa) { ETHQOSERR("Null Param eth_ipa %pK\n", eth_ipa); return; } if (!ntn_ipa->ipa_offload_conn) { if (!eth_ipa->ipa_offload_conn) { ETHQOSERR("ipa_cb before offload is ready %d\n", ntn_ipa->ipa_offload_conn); eth_ipa->ipa_offload_conn); return; } Loading Loading @@ -1065,7 +1065,7 @@ static int ethqos_ipa_offload_init(struct qcom_ethqos *pdata) { struct ipa_uc_offload_intf_params in; struct ipa_uc_offload_out_params out; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct ethhdr eth_l2_hdr_v4; struct ethhdr eth_l2_hdr_v6; #ifdef ETHQOS_IPA_OFFLOAD_VLAN Loading Loading @@ -1145,9 +1145,9 @@ static int ethqos_ipa_offload_init(struct qcom_ethqos *pdata) ret = -1; return ret; } ntn_ipa->ipa_client_hndl = out.clnt_hndl; eth_ipa->ipa_client_hndl = out.clnt_hndl; ETHQOSDBG("Recevied IPA Offload Client Handle %d", ntn_ipa->ipa_client_hndl); eth_ipa->ipa_client_hndl); pdata->ipa_enabled = true; return 0; Loading @@ -1155,7 +1155,7 @@ static int ethqos_ipa_offload_init(struct qcom_ethqos *pdata) static int ethqos_ipa_offload_cleanup(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; int ret = 0; ETHQOSDBG("begin\n"); Loading @@ -1165,12 +1165,12 @@ static int ethqos_ipa_offload_cleanup(struct qcom_ethqos *ethqos) return -ENOMEM; } if (!ntn_ipa->ipa_client_hndl) { if (!eth_ipa->ipa_client_hndl) { ETHQOSERR("cleanup called with NULL IPA client handle\n"); return -ENOMEM; } ret = ipa_uc_offload_cleanup(ntn_ipa->ipa_client_hndl); ret = ipa_uc_offload_cleanup(eth_ipa->ipa_client_hndl); if (ret) { ETHQOSERR("Could not cleanup IPA Offload ret %d\n", ret); ret = -1; Loading @@ -1183,14 +1183,23 @@ static int ethqos_ipa_offload_cleanup(struct qcom_ethqos *ethqos) return ret; } static bool ethqos_is_phy_link_up(struct stmmac_priv *priv) static inline void *ethqos_get_priv(struct qcom_ethqos *ethqos) { struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); return priv; } static bool ethqos_is_phy_link_up(struct qcom_ethqos *ethqos) { /* PHY driver initializes phydev->link=1. * So, phydev->link is 1 even on booup with no PHY connected. * phydev->link is valid only after adjust_link is called once. * Use (pdata->oldlink != -1) to indicate phy link is not up */ struct qcom_ethqos *ethqos = priv->plat->bsp_priv; struct stmmac_priv *priv = ethqos_get_priv(ethqos); return ethqos->always_on_phy ? 1 : ((priv->oldlink != -1) && priv->dev->phydev && priv->dev->phydev->link); Loading @@ -1202,11 +1211,8 @@ static ssize_t read_ipa_offload_status(struct file *file, { unsigned int len = 0, buf_len = NTN_IPA_DBG_MAX_MSG_LEN; struct qcom_ethqos *ethqos = file->private_data; struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); if (ethqos_is_phy_link_up(priv)) { if (ethqos_is_phy_link_up(ethqos)) { if (eth_ipa_ctx.ipa_offload_susp) len += scnprintf(buf + len, buf_len - len, "IPA Offload suspended\n"); Loading Loading @@ -1259,7 +1265,7 @@ static ssize_t suspend_resume_ipa_offload(struct file *file, if (kstrtos8(in_buf, 0, &option)) return -EFAULT; if (ethqos_is_phy_link_up(priv)) { if (ethqos_is_phy_link_up(ethqos)) { if (option == 1) ethqos_ipa_offload_event_handler(priv, EV_USR_SUSPEND); else if (option == 0) Loading @@ -1276,12 +1282,12 @@ static ssize_t read_ipa_stats(struct file *file, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; char *buf; unsigned int len = 0, buf_len = 2000; ssize_t ret_cnt; if (!ethqos || !ntn_ipa) { if (!ethqos || !eth_ipa) { ETHQOSERR("NULL Pointer\n"); return -EINVAL; } Loading Loading @@ -1410,7 +1416,7 @@ static ssize_t read_ntn_dma_stats(struct file *file, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct ethqos_ipa_stats *dma_stats = ð_ipa_ctx.ipa_stats; char *buf; unsigned int len = 0, buf_len = 3000; Loading Loading @@ -1446,7 +1452,7 @@ static ssize_t read_ntn_dma_stats(struct file *file, "RX Tail Pointer Index: ", dma_stats->ipa_rx_tail_ptr_indx); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", "RX Doorbell Address: ", ntn_ipa->uc_db_rx_addr); "RX Doorbell Address: ", eth_ipa->uc_db_rx_addr); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", Loading Loading @@ -1501,7 +1507,7 @@ static ssize_t read_ntn_dma_stats(struct file *file, len += scnprintf(buf + len, buf_len - len, "%-50s %10lu\n", "TX Tail Pointer Index: ", dma_stats->ipa_tx_tail_ptr_indx); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", "TX Doorbell Address: ", ntn_ipa->uc_db_tx_addr); "TX Doorbell Address: ", eth_ipa->uc_db_tx_addr); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%-50s 0x%x\n", Loading Loading @@ -1577,22 +1583,22 @@ static const struct file_operations fops_ntn_ipa_offload_en = { static int ethqos_ipa_cleanup_debugfs(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; if (!ethqos || !ntn_ipa) { if (!ethqos || !eth_ipa) { ETHQOSERR("Null Param\n"); return -ENOMEM; } if (ethqos->debugfs_dir) { debugfs_remove(ntn_ipa->debugfs_ipa_stats); ntn_ipa->debugfs_ipa_stats = NULL; debugfs_remove(eth_ipa->debugfs_ipa_stats); eth_ipa->debugfs_ipa_stats = NULL; debugfs_remove(ntn_ipa->debugfs_dma_stats); ntn_ipa->debugfs_dma_stats = NULL; debugfs_remove(eth_ipa->debugfs_dma_stats); eth_ipa->debugfs_dma_stats = NULL; debugfs_remove(ntn_ipa->debugfs_suspend_ipa_offload); ntn_ipa->debugfs_suspend_ipa_offload = NULL; debugfs_remove(eth_ipa->debugfs_suspend_ipa_offload); eth_ipa->debugfs_suspend_ipa_offload = NULL; } ETHQOSDBG("IPA debugfs Deleted Successfully\n"); Loading @@ -1608,38 +1614,38 @@ static int ethqos_ipa_cleanup_debugfs(struct qcom_ethqos *ethqos) */ static int ethqos_ipa_create_debugfs(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; ntn_ipa->debugfs_suspend_ipa_offload = eth_ipa->debugfs_suspend_ipa_offload = debugfs_create_file("suspend_ipa_offload", 0600, ethqos->debugfs_dir, ethqos, &fops_ntn_ipa_offload_en); if (!ntn_ipa->debugfs_suspend_ipa_offload || IS_ERR(ntn_ipa->debugfs_suspend_ipa_offload)) { if (!eth_ipa->debugfs_suspend_ipa_offload || IS_ERR(eth_ipa->debugfs_suspend_ipa_offload)) { ETHQOSERR("Cannot create debugfs ipa_offload_en %d\n", (int)ntn_ipa->debugfs_suspend_ipa_offload); (int)eth_ipa->debugfs_suspend_ipa_offload); goto fail; } ntn_ipa->debugfs_ipa_stats = eth_ipa->debugfs_ipa_stats = debugfs_create_file("ipa_stats", 0600, ethqos->debugfs_dir, ethqos, &fops_ipa_stats); if (!ntn_ipa->debugfs_ipa_stats || IS_ERR(ntn_ipa->debugfs_ipa_stats)) { if (!eth_ipa->debugfs_ipa_stats || IS_ERR(eth_ipa->debugfs_ipa_stats)) { ETHQOSERR("Cannot create debugfs_ipa_stats %d\n", (int)ntn_ipa->debugfs_ipa_stats); (int)eth_ipa->debugfs_ipa_stats); goto fail; } ntn_ipa->debugfs_dma_stats = eth_ipa->debugfs_dma_stats = debugfs_create_file("dma_stats", 0600, ethqos->debugfs_dir, ethqos, &fops_ntn_dma_stats); if (!ntn_ipa->debugfs_suspend_ipa_offload || IS_ERR(ntn_ipa->debugfs_suspend_ipa_offload)) { if (!eth_ipa->debugfs_suspend_ipa_offload || IS_ERR(eth_ipa->debugfs_suspend_ipa_offload)) { ETHQOSERR("Cannot create debugfs_dma_stats %d\n", (int)ntn_ipa->debugfs_dma_stats); (int)eth_ipa->debugfs_dma_stats); goto fail; } Loading @@ -1652,7 +1658,7 @@ static int ethqos_ipa_create_debugfs(struct qcom_ethqos *ethqos) static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; struct ipa_uc_offload_conn_in_params in; struct ipa_uc_offload_conn_out_params out; struct ipa_ntn_setup_info rx_setup_info = {0}; Loading @@ -1678,7 +1684,7 @@ static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) memset(&out, 0, sizeof(out)); memset(&profile, 0, sizeof(profile)); in.clnt_hndl = ntn_ipa->ipa_client_hndl; in.clnt_hndl = eth_ipa->ipa_client_hndl; /* Uplink Setup */ if (emac_emb_smmu_ctx.valid) Loading Loading @@ -1798,8 +1804,8 @@ static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) goto mem_free; } ntn_ipa->uc_db_rx_addr = out.u.ntn.ul_uc_db_pa; ntn_ipa->uc_db_tx_addr = out.u.ntn.dl_uc_db_pa; eth_ipa->uc_db_rx_addr = out.u.ntn.ul_uc_db_pa; eth_ipa->uc_db_tx_addr = out.u.ntn.dl_uc_db_pa; /* Set Perf Profile For PROD/CONS Pipes */ profile.max_supported_bw_mbps = ethqos->speed; Loading Loading @@ -1857,7 +1863,7 @@ static int ethqos_ipa_offload_connect(struct qcom_ethqos *ethqos) static int ethqos_ipa_offload_disconnect(struct qcom_ethqos *ethqos) { struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; int ret = 0; ETHQOSDBG("- begin\n"); Loading @@ -1867,7 +1873,7 @@ static int ethqos_ipa_offload_disconnect(struct qcom_ethqos *ethqos) return -ENOMEM; } ret = ipa_uc_offload_disconn_pipes(ntn_ipa->ipa_client_hndl); ret = ipa_uc_offload_disconn_pipes(eth_ipa->ipa_client_hndl); if (ret) { ETHQOSERR("Could not cleanup IPA Offload ret %d\n", ret); return ret; Loading Loading @@ -2129,7 +2135,7 @@ static void ethqos_ipaucrdy_wq(struct work_struct *work) static void ethqos_ipa_uc_ready_cb(void *user_data) { struct qcom_ethqos *pdata = (struct qcom_ethqos *)user_data; struct ethqos_prv_ipa_data *ntn_ipa = ð_ipa_ctx; struct ethqos_prv_ipa_data *eth_ipa = ð_ipa_ctx; if (!pdata) { ETHQOSERR("Null Param pdata %pK\n", pdata); Loading @@ -2137,8 +2143,8 @@ static void ethqos_ipa_uc_ready_cb(void *user_data) } ETHQOSDBG("Received IPA UC ready callback\n"); INIT_WORK(&ntn_ipa->ntn_ipa_rdy_work, ethqos_ipaucrdy_wq); queue_work(system_unbound_wq, &ntn_ipa->ntn_ipa_rdy_work); INIT_WORK(ð_ipa->ntn_ipa_rdy_work, ethqos_ipaucrdy_wq); queue_work(system_unbound_wq, ð_ipa->ntn_ipa_rdy_work); } static int ethqos_ipa_uc_ready(struct qcom_ethqos *pdata) Loading @@ -2165,10 +2171,14 @@ static int ethqos_ipa_uc_ready(struct qcom_ethqos *pdata) void ethqos_ipa_offload_event_handler(void *data, int ev) { struct stmmac_priv *priv = data; struct qcom_ethqos *pdata = priv->plat->bsp_priv; ETHQOSDBG("Enter: event=%d\n", ev); if (ev == EV_PROBE_INIT) { eth_ipa_ctx.ethqos = data; mutex_init(ð_ipa_ctx.ipa_lock); return; } IPA_LOCK(); switch (ev) { Loading @@ -2181,7 +2191,7 @@ void ethqos_ipa_offload_event_handler(void *data, !eth_ipa_ctx.ipa_offload_conn) break; if (!ethqos_ipa_offload_suspend(pdata)) if (!ethqos_ipa_offload_suspend(eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_link_down = true; } break; Loading @@ -2194,43 +2204,39 @@ void ethqos_ipa_offload_event_handler(void *data, /* Link up event is expected only after link down */ if (eth_ipa_ctx.ipa_offload_link_down) { ethqos_ipa_offload_resume(pdata); ethqos_ipa_offload_resume(eth_ipa_ctx.ethqos); } else if (eth_ipa_ctx.emac_dev_ready && eth_ipa_ctx.ipa_uc_ready) { ethqos_enable_ipa_offload(pdata); ethqos_enable_ipa_offload(eth_ipa_ctx.ethqos); } eth_ipa_ctx.ipa_offload_link_down = false; } break; case EV_DEV_OPEN: { eth_ipa_ctx.ethqos = pdata; ethqos_ipa_config_queues(pdata); ethqos_ipa_config_queues(eth_ipa_ctx.ethqos); eth_ipa_ctx.emac_dev_ready = true; if (!eth_ipa_ctx.ipa_ready) ethqos_ipa_ready(pdata); ethqos_ipa_ready(eth_ipa_ctx.ethqos); if (!eth_ipa_ctx.ipa_uc_ready) ethqos_ipa_uc_ready(pdata); ethqos_ipa_uc_ready(eth_ipa_ctx.ethqos); } break; case EV_IPA_READY: { eth_ipa_ctx.ipa_ready = true; if (!eth_ipa_ctx.ipa_uc_ready) ethqos_ipa_uc_ready(pdata); ethqos_ipa_uc_ready(eth_ipa_ctx.ethqos); if (eth_ipa_ctx.ipa_uc_ready && ethqos_is_phy_link_up(priv)) ethqos_enable_ipa_offload(pdata); ethqos_is_phy_link_up(eth_ipa_ctx.ethqos)) ethqos_enable_ipa_offload(eth_ipa_ctx.ethqos); } break; case EV_IPA_UC_READY: { eth_ipa_ctx.ipa_uc_ready = true; Loading @@ -2240,16 +2246,16 @@ void ethqos_ipa_offload_event_handler(void *data, break; if (eth_ipa_ctx.ipa_ready) { if (!eth_ipa_ctx.ipa_offload_init) { if (!ethqos_ipa_offload_init(pdata)) if (!ethqos_ipa_offload_init( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_init = true; } } if (ethqos_is_phy_link_up(priv)) ethqos_enable_ipa_offload(pdata); if (ethqos_is_phy_link_up(eth_ipa_ctx.ethqos)) ethqos_enable_ipa_offload(eth_ipa_ctx.ethqos); } break; case EV_DEV_CLOSE: { eth_ipa_ctx.emac_dev_ready = false; Loading @@ -2257,27 +2263,35 @@ void ethqos_ipa_offload_event_handler(void *data, if (eth_ipa_ctx.ipa_uc_ready) ipa_uc_offload_dereg_rdyCB(IPA_UC_NTN); ethqos_disable_ipa_offload(pdata); ethqos_disable_ipa_offload(eth_ipa_ctx.ethqos); /* reset link down on dev close */ eth_ipa_ctx.ipa_offload_link_down = 0; } break; case EV_DPM_SUSPEND: { if (eth_ipa_ctx.ipa_offload_conn) *(int *)data = false; else *(int *)data = true; } break; case EV_USR_SUSPEND: { if (!eth_ipa_ctx.ipa_offload_susp && !eth_ipa_ctx.ipa_offload_link_down) if (!ethqos_ipa_offload_suspend(pdata)) eth_ipa_ctx.ipa_offload_susp = true; if (!ethqos_ipa_offload_suspend( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_susp = true; } break; case EV_DPM_RESUME: { if (eth_ipa_ctx.ipa_offload_susp) { if (ethqos_is_phy_link_up(priv)) { if (!ethqos_ipa_offload_resume(pdata)) if (ethqos_is_phy_link_up(eth_ipa_ctx.ethqos)) { if (!ethqos_ipa_offload_resume( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_susp = false; } else { Loading @@ -2294,24 +2308,25 @@ void ethqos_ipa_offload_event_handler(void *data, = true; } } } break; case EV_USR_RESUME: { if (eth_ipa_ctx.ipa_offload_susp) { if (!ethqos_ipa_offload_resume(pdata)) eth_ipa_ctx.ipa_offload_susp = false; if (!ethqos_ipa_offload_resume( eth_ipa_ctx.ethqos)) eth_ipa_ctx.ipa_offload_susp = false; } } break; case EV_IPA_OFFLOAD_REMOVE: { ethqos_rx_buf_free_mem(pdata, IPA_DMA_RX_CH); ethqos_tx_buf_free_mem(pdata, IPA_DMA_TX_CH); ethqos_rx_desc_free_mem(pdata, IPA_DMA_RX_CH); ethqos_tx_desc_free_mem(pdata, IPA_DMA_TX_CH); ethqos_free_ipa_rx_queue_struct(pdata); ethqos_free_ipa_tx_queue_struct(pdata); ethqos_rx_buf_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_RX_CH); ethqos_tx_buf_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_TX_CH); ethqos_rx_desc_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_RX_CH); ethqos_tx_desc_free_mem(eth_ipa_ctx.ethqos, IPA_DMA_TX_CH); ethqos_free_ipa_rx_queue_struct(eth_ipa_ctx.ethqos); ethqos_free_ipa_tx_queue_struct(eth_ipa_ctx.ethqos); } break; case EV_INVALID: Loading