Loading drivers/net/ethernet/stmicro/stmmac/chain_mode.c +2 −2 Original line number Diff line number Diff line Loading @@ -43,10 +43,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) len = nopaged_len - bmax; des2 = dma_map_single(priv->device, skb->data, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data, bmax, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; tx_q->tx_skbuff_dma[entry].len = bmax; Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +311 −6 Original line number Diff line number Diff line Loading @@ -13,9 +13,11 @@ #include <linux/mii.h> #include <linux/of_mdio.h> #include <linux/slab.h> #include <linux/ipc_logging.h> #include <linux/poll.h> #include <linux/debugfs.h> #include <asm/dma-iommu.h> #include <linux/iommu.h> #include "stmmac.h" #include "stmmac_platform.h" Loading Loading @@ -101,6 +103,9 @@ bool phy_intr_en; struct qcom_ethqos *pethqos; struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0}; void *ipc_emac_log_ctxt; static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) { Loading Loading @@ -599,6 +604,286 @@ static void ethqos_pps_irq_config(struct qcom_ethqos *ethqos) } } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,sdxprairie-ethqos", .data = &emac_v2_3_2_por}, { .compatible = "qcom,emac-smmu-embedded", }, { } }; static ssize_t read_phy_reg_dump(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; unsigned int len = 0, buf_len = 2000; char *buf; ssize_t ret_cnt; int phydata = 0; int i = 0; struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); if (!ethqos || !dev->phydev) { ETHQOSERR("NULL Pointer\n"); return -EINVAL; } buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; len += scnprintf(buf + len, buf_len - len, "\n************* PHY Reg dump *************\n"); for (i = 0; i < 32; i++) { phydata = ethqos_mdio_read(priv, priv->plat->phy_addr, i); len += scnprintf(buf + len, buf_len - len, "MII Register (%#x) = %#x\n", i, phydata); } if (len > buf_len) { ETHQOSERR("(len > buf_len) buffer not sufficient\n"); len = buf_len; } ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret_cnt; } static ssize_t read_rgmii_reg_dump(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; unsigned int len = 0, buf_len = 2000; char *buf; ssize_t ret_cnt; int rgmii_data = 0; struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); if (!ethqos || !dev->phydev) { ETHQOSERR("NULL Pointer\n"); return -EINVAL; } buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; len += scnprintf(buf + len, buf_len - len, "\n************* RGMII Reg dump *************\n"); rgmii_data = rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG); len += scnprintf(buf + len, buf_len - len, "RGMII_IO_MACRO_CONFIG Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); len += scnprintf(buf + len, buf_len - len, "SDCC_HC_REG_DLL_CONFIG Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG); len += scnprintf(buf + len, buf_len - len, "SDCC_HC_REG_DDR_CONFIG Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2); len += scnprintf(buf + len, buf_len - len, "SDCC_HC_REG_DLL_CONFIG2 Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDC4_STATUS); len += scnprintf(buf + len, buf_len - len, "SDC4_STATUS Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_USR_CTL); len += scnprintf(buf + len, buf_len - len, "SDCC_USR_CTL Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2); len += scnprintf(buf + len, buf_len - len, "RGMII_IO_MACRO_CONFIG2 Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1); len += scnprintf(buf + len, buf_len - len, "RGMII_IO_MACRO_DEBUG1 Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG); len += scnprintf(buf + len, buf_len - len, "EMAC_SYSTEM_LOW_POWER_DEBUG Register = %#x\n", rgmii_data); if (len > buf_len) { ETHQOSERR("(len > buf_len) buffer not sufficient\n"); len = buf_len; } ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret_cnt; } static const struct file_operations fops_phy_reg_dump = { .read = read_phy_reg_dump, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static const struct file_operations fops_rgmii_reg_dump = { .read = read_rgmii_reg_dump, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static int ethqos_create_debugfs(struct qcom_ethqos *ethqos) { static struct dentry *phy_reg_dump; static struct dentry *rgmii_reg_dump; if (!ethqos) { ETHQOSERR("Null Param %s\n", __func__); return -ENOMEM; } ethqos->debugfs_dir = debugfs_create_dir("eth", NULL); if (!ethqos->debugfs_dir || IS_ERR(ethqos->debugfs_dir)) { ETHQOSERR("Can't create debugfs dir\n"); return -ENOMEM; } phy_reg_dump = debugfs_create_file("phy_reg_dump", 0400, ethqos->debugfs_dir, ethqos, &fops_phy_reg_dump); if (!phy_reg_dump || IS_ERR(phy_reg_dump)) { ETHQOSERR("Can't create phy_dump %d\n", (int)phy_reg_dump); goto fail; } rgmii_reg_dump = debugfs_create_file("rgmii_reg_dump", 0400, ethqos->debugfs_dir, ethqos, &fops_rgmii_reg_dump); if (!rgmii_reg_dump || IS_ERR(rgmii_reg_dump)) { ETHQOSERR("Can't create rgmii_dump %d\n", (int)rgmii_reg_dump); goto fail; } return 0; fail: debugfs_remove_recursive(ethqos->debugfs_dir); return -ENOMEM; } static void emac_emb_smmu_exit(void) { if (emac_emb_smmu_ctx.valid) { if (emac_emb_smmu_ctx.smmu_pdev) arm_iommu_detach_device (&emac_emb_smmu_ctx.smmu_pdev->dev); if (emac_emb_smmu_ctx.mapping) arm_iommu_release_mapping(emac_emb_smmu_ctx.mapping); emac_emb_smmu_ctx.valid = false; emac_emb_smmu_ctx.mapping = NULL; emac_emb_smmu_ctx.pdev_master = NULL; emac_emb_smmu_ctx.smmu_pdev = NULL; } } static int emac_emb_smmu_cb_probe(struct platform_device *pdev) { int result; u32 iova_ap_mapping[2]; struct device *dev = &pdev->dev; int atomic_ctx = 1; int fast = 1; int bypass = 1; ETHQOSDBG("EMAC EMB SMMU CB probe: smmu pdev=%p\n", pdev); result = of_property_read_u32_array(dev->of_node, "qcom,iova-mapping", iova_ap_mapping, 2); if (result) { ETHQOSERR("Failed to read EMB start/size iova addresses\n"); return result; } emac_emb_smmu_ctx.va_start = iova_ap_mapping[0]; emac_emb_smmu_ctx.va_size = iova_ap_mapping[1]; emac_emb_smmu_ctx.va_end = emac_emb_smmu_ctx.va_start + emac_emb_smmu_ctx.va_size; emac_emb_smmu_ctx.smmu_pdev = pdev; if (dma_set_mask(dev, DMA_BIT_MASK(32)) || dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) { ETHQOSERR("DMA set 32bit mask failed\n"); return -EOPNOTSUPP; } emac_emb_smmu_ctx.mapping = arm_iommu_create_mapping (dev->bus, emac_emb_smmu_ctx.va_start, emac_emb_smmu_ctx.va_size); if (IS_ERR_OR_NULL(emac_emb_smmu_ctx.mapping)) { ETHQOSDBG("Fail to create mapping\n"); /* assume this failure is because iommu driver is not ready */ return -EPROBE_DEFER; } ETHQOSDBG("Successfully Created SMMU mapping\n"); emac_emb_smmu_ctx.valid = true; if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass")) { if (iommu_domain_set_attr(emac_emb_smmu_ctx.mapping->domain, DOMAIN_ATTR_S1_BYPASS, &bypass)) { ETHQOSERR("Couldn't set SMMU S1 bypass\n"); result = -EIO; goto err_smmu_probe; } ETHQOSDBG("SMMU S1 BYPASS set\n"); } else { if (iommu_domain_set_attr(emac_emb_smmu_ctx.mapping->domain, DOMAIN_ATTR_ATOMIC, &atomic_ctx)) { ETHQOSERR("Couldn't set SMMU domain as atomic\n"); result = -EIO; goto err_smmu_probe; } ETHQOSDBG("SMMU atomic set\n"); if (iommu_domain_set_attr(emac_emb_smmu_ctx.mapping->domain, DOMAIN_ATTR_FAST, &fast)) { ETHQOSERR("Couldn't set FAST SMMU\n"); result = -EIO; goto err_smmu_probe; } ETHQOSDBG("SMMU fast map set\n"); } result = arm_iommu_attach_device(&emac_emb_smmu_ctx.smmu_pdev->dev, emac_emb_smmu_ctx.mapping); if (result) { ETHQOSERR("couldn't attach to IOMMU ret=%d\n", result); goto err_smmu_probe; } emac_emb_smmu_ctx.iommu_domain = iommu_get_domain_for_dev(&emac_emb_smmu_ctx.smmu_pdev->dev); ETHQOSDBG("Successfully attached to IOMMU\n"); if (emac_emb_smmu_ctx.pdev_master) goto smmu_probe_done; err_smmu_probe: if (emac_emb_smmu_ctx.mapping) arm_iommu_release_mapping(emac_emb_smmu_ctx.mapping); emac_emb_smmu_ctx.valid = false; smmu_probe_done: emac_emb_smmu_ctx.ret = result; return result; } static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; Loading @@ -608,6 +893,15 @@ static int qcom_ethqos_probe(struct platform_device *pdev) struct resource *res; int ret; ipc_emac_log_ctxt = ipc_log_context_create(IPCLOG_STATE_PAGES, "emac", 0); if (!ipc_emac_log_ctxt) ETHQOSERR("Error creating logging context for emac\n"); else ETHQOSDBG("IPC logging has been enabled for emac\n"); if (of_device_is_compatible(pdev->dev.of_node, "qcom,emac-smmu-embedded")) return emac_emb_smmu_cb_probe(pdev); ret = stmmac_get_platform_resources(pdev, &stmmac_res); if (ret) return ret; Loading Loading @@ -659,6 +953,20 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->pmt = 1; plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); if (of_property_read_bool(pdev->dev.of_node, "qcom,arm-smmu")) { emac_emb_smmu_ctx.pdev_master = pdev; ret = of_platform_populate(pdev->dev.of_node, qcom_ethqos_match, NULL, &pdev->dev); if (ret) ETHQOSERR("Failed to populate EMAC platform\n"); if (emac_emb_smmu_ctx.ret) { ETHQOSERR("smmu probe failed\n"); of_platform_depopulate(&pdev->dev); ret = emac_emb_smmu_ctx.ret; emac_emb_smmu_ctx.ret = 0; } } ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_clk; Loading Loading @@ -686,6 +994,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) } pethqos = ethqos; ethqos_create_debugfs(ethqos); return ret; err_clk: Loading @@ -711,16 +1020,12 @@ static int qcom_ethqos_remove(struct platform_device *pdev) if (phy_intr_en) free_irq(ethqos->phy_intr, ethqos); emac_emb_smmu_exit(); ethqos_disable_regulators(ethqos); return ret; } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por}, { .compatible = "qcom,sdxprairie-ethqos", .data = &emac_v2_3_2_por}, { } }; MODULE_DEVICE_TABLE(of, qcom_ethqos_match); static struct platform_driver qcom_ethqos_driver = { Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h +17 −2 Original line number Diff line number Diff line Loading @@ -12,14 +12,28 @@ #ifndef _DWMAC_QCOM_ETHQOS_H #define _DWMAC_QCOM_ETHQOS_H #include <linux/ipc_logging.h> extern void *ipc_emac_log_ctxt; #define IPCLOG_STATE_PAGES 50 #define __FILENAME__ (strrchr(__FILE__, '/') ? \ strrchr(__FILE__, '/') + 1 : __FILE__) #define DRV_NAME "qcom-ethqos" #define ETHQOSDBG(fmt, args...) \ pr_debug(DRV_NAME " %s:%d " fmt, __func__, ## args) #define ETHQOSERR(fmt, args...) \ pr_err(DRV_NAME " %s:%d " fmt, __func__, ## args) do {\ pr_err(DRV_NAME " %s:%d " fmt, __func__, ## args);\ if (ipc_emac_log_ctxt) { \ ipc_log_string(ipc_emac_log_ctxt, \ "%s: %s[%u]:[emac] ERROR:" fmt, __FILENAME__,\ __func__, __LINE__, ## args); \ } \ } while (0) #define ETHQOSINFO(fmt, args...) \ pr_info(DRV_NAME " %s:%d " fmt, __func__, ## args) #define RGMII_IO_MACRO_CONFIG 0x0 #define SDCC_HC_REG_DLL_CONFIG 0x4 #define SDCC_HC_REG_DDR_CONFIG 0xC Loading Loading @@ -130,6 +144,7 @@ struct qcom_ethqos { unsigned long avb_class_a_intr_cnt; unsigned long avb_class_b_intr_cnt; struct dentry *debugfs_dir; }; struct pps_cfg { Loading drivers/net/ethernet/stmicro/stmmac/ring_mode.c +6 −6 Original line number Diff line number Diff line Loading @@ -47,10 +47,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) if (nopaged_len > BUF_SIZE_8KiB) { des2 = dma_map_single(priv->device, skb->data, bmax, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data, bmax, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; Loading @@ -69,10 +69,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) else desc = tx_q->dma_tx + entry; des2 = dma_map_single(priv->device, skb->data + bmax, len, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data + bmax, len, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; tx_q->tx_skbuff_dma[entry].len = len; Loading @@ -83,10 +83,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) STMMAC_RING_MODE, 1, true, skb->len); } else { des2 = dma_map_single(priv->device, skb->data, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data, nopaged_len, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; tx_q->tx_skbuff_dma[entry].len = nopaged_len; Loading drivers/net/ethernet/stmicro/stmmac/stmmac.h +17 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,23 @@ struct stmmac_priv { #endif }; struct emac_emb_smmu_cb_ctx { bool valid; struct platform_device *pdev_master; struct platform_device *smmu_pdev; struct dma_iommu_mapping *mapping; struct iommu_domain *iommu_domain; u32 va_start; u32 va_size; u32 va_end; int ret; }; extern struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx; #define GET_MEM_PDEV_DEV (emac_emb_smmu_ctx.valid ? \ &emac_emb_smmu_ctx.smmu_pdev->dev : priv->device) int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); extern bool phy_intr_en; Loading Loading
drivers/net/ethernet/stmicro/stmmac/chain_mode.c +2 −2 Original line number Diff line number Diff line Loading @@ -43,10 +43,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) len = nopaged_len - bmax; des2 = dma_map_single(priv->device, skb->data, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data, bmax, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; tx_q->tx_skbuff_dma[entry].len = bmax; Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +311 −6 Original line number Diff line number Diff line Loading @@ -13,9 +13,11 @@ #include <linux/mii.h> #include <linux/of_mdio.h> #include <linux/slab.h> #include <linux/ipc_logging.h> #include <linux/poll.h> #include <linux/debugfs.h> #include <asm/dma-iommu.h> #include <linux/iommu.h> #include "stmmac.h" #include "stmmac_platform.h" Loading Loading @@ -101,6 +103,9 @@ bool phy_intr_en; struct qcom_ethqos *pethqos; struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0}; void *ipc_emac_log_ctxt; static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) { Loading Loading @@ -599,6 +604,286 @@ static void ethqos_pps_irq_config(struct qcom_ethqos *ethqos) } } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,sdxprairie-ethqos", .data = &emac_v2_3_2_por}, { .compatible = "qcom,emac-smmu-embedded", }, { } }; static ssize_t read_phy_reg_dump(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; unsigned int len = 0, buf_len = 2000; char *buf; ssize_t ret_cnt; int phydata = 0; int i = 0; struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(dev); if (!ethqos || !dev->phydev) { ETHQOSERR("NULL Pointer\n"); return -EINVAL; } buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; len += scnprintf(buf + len, buf_len - len, "\n************* PHY Reg dump *************\n"); for (i = 0; i < 32; i++) { phydata = ethqos_mdio_read(priv, priv->plat->phy_addr, i); len += scnprintf(buf + len, buf_len - len, "MII Register (%#x) = %#x\n", i, phydata); } if (len > buf_len) { ETHQOSERR("(len > buf_len) buffer not sufficient\n"); len = buf_len; } ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret_cnt; } static ssize_t read_rgmii_reg_dump(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct qcom_ethqos *ethqos = file->private_data; unsigned int len = 0, buf_len = 2000; char *buf; ssize_t ret_cnt; int rgmii_data = 0; struct platform_device *pdev = ethqos->pdev; struct net_device *dev = platform_get_drvdata(pdev); if (!ethqos || !dev->phydev) { ETHQOSERR("NULL Pointer\n"); return -EINVAL; } buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; len += scnprintf(buf + len, buf_len - len, "\n************* RGMII Reg dump *************\n"); rgmii_data = rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG); len += scnprintf(buf + len, buf_len - len, "RGMII_IO_MACRO_CONFIG Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); len += scnprintf(buf + len, buf_len - len, "SDCC_HC_REG_DLL_CONFIG Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG); len += scnprintf(buf + len, buf_len - len, "SDCC_HC_REG_DDR_CONFIG Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2); len += scnprintf(buf + len, buf_len - len, "SDCC_HC_REG_DLL_CONFIG2 Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDC4_STATUS); len += scnprintf(buf + len, buf_len - len, "SDC4_STATUS Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, SDCC_USR_CTL); len += scnprintf(buf + len, buf_len - len, "SDCC_USR_CTL Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2); len += scnprintf(buf + len, buf_len - len, "RGMII_IO_MACRO_CONFIG2 Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1); len += scnprintf(buf + len, buf_len - len, "RGMII_IO_MACRO_DEBUG1 Register = %#x\n", rgmii_data); rgmii_data = rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG); len += scnprintf(buf + len, buf_len - len, "EMAC_SYSTEM_LOW_POWER_DEBUG Register = %#x\n", rgmii_data); if (len > buf_len) { ETHQOSERR("(len > buf_len) buffer not sufficient\n"); len = buf_len; } ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret_cnt; } static const struct file_operations fops_phy_reg_dump = { .read = read_phy_reg_dump, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static const struct file_operations fops_rgmii_reg_dump = { .read = read_rgmii_reg_dump, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static int ethqos_create_debugfs(struct qcom_ethqos *ethqos) { static struct dentry *phy_reg_dump; static struct dentry *rgmii_reg_dump; if (!ethqos) { ETHQOSERR("Null Param %s\n", __func__); return -ENOMEM; } ethqos->debugfs_dir = debugfs_create_dir("eth", NULL); if (!ethqos->debugfs_dir || IS_ERR(ethqos->debugfs_dir)) { ETHQOSERR("Can't create debugfs dir\n"); return -ENOMEM; } phy_reg_dump = debugfs_create_file("phy_reg_dump", 0400, ethqos->debugfs_dir, ethqos, &fops_phy_reg_dump); if (!phy_reg_dump || IS_ERR(phy_reg_dump)) { ETHQOSERR("Can't create phy_dump %d\n", (int)phy_reg_dump); goto fail; } rgmii_reg_dump = debugfs_create_file("rgmii_reg_dump", 0400, ethqos->debugfs_dir, ethqos, &fops_rgmii_reg_dump); if (!rgmii_reg_dump || IS_ERR(rgmii_reg_dump)) { ETHQOSERR("Can't create rgmii_dump %d\n", (int)rgmii_reg_dump); goto fail; } return 0; fail: debugfs_remove_recursive(ethqos->debugfs_dir); return -ENOMEM; } static void emac_emb_smmu_exit(void) { if (emac_emb_smmu_ctx.valid) { if (emac_emb_smmu_ctx.smmu_pdev) arm_iommu_detach_device (&emac_emb_smmu_ctx.smmu_pdev->dev); if (emac_emb_smmu_ctx.mapping) arm_iommu_release_mapping(emac_emb_smmu_ctx.mapping); emac_emb_smmu_ctx.valid = false; emac_emb_smmu_ctx.mapping = NULL; emac_emb_smmu_ctx.pdev_master = NULL; emac_emb_smmu_ctx.smmu_pdev = NULL; } } static int emac_emb_smmu_cb_probe(struct platform_device *pdev) { int result; u32 iova_ap_mapping[2]; struct device *dev = &pdev->dev; int atomic_ctx = 1; int fast = 1; int bypass = 1; ETHQOSDBG("EMAC EMB SMMU CB probe: smmu pdev=%p\n", pdev); result = of_property_read_u32_array(dev->of_node, "qcom,iova-mapping", iova_ap_mapping, 2); if (result) { ETHQOSERR("Failed to read EMB start/size iova addresses\n"); return result; } emac_emb_smmu_ctx.va_start = iova_ap_mapping[0]; emac_emb_smmu_ctx.va_size = iova_ap_mapping[1]; emac_emb_smmu_ctx.va_end = emac_emb_smmu_ctx.va_start + emac_emb_smmu_ctx.va_size; emac_emb_smmu_ctx.smmu_pdev = pdev; if (dma_set_mask(dev, DMA_BIT_MASK(32)) || dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) { ETHQOSERR("DMA set 32bit mask failed\n"); return -EOPNOTSUPP; } emac_emb_smmu_ctx.mapping = arm_iommu_create_mapping (dev->bus, emac_emb_smmu_ctx.va_start, emac_emb_smmu_ctx.va_size); if (IS_ERR_OR_NULL(emac_emb_smmu_ctx.mapping)) { ETHQOSDBG("Fail to create mapping\n"); /* assume this failure is because iommu driver is not ready */ return -EPROBE_DEFER; } ETHQOSDBG("Successfully Created SMMU mapping\n"); emac_emb_smmu_ctx.valid = true; if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass")) { if (iommu_domain_set_attr(emac_emb_smmu_ctx.mapping->domain, DOMAIN_ATTR_S1_BYPASS, &bypass)) { ETHQOSERR("Couldn't set SMMU S1 bypass\n"); result = -EIO; goto err_smmu_probe; } ETHQOSDBG("SMMU S1 BYPASS set\n"); } else { if (iommu_domain_set_attr(emac_emb_smmu_ctx.mapping->domain, DOMAIN_ATTR_ATOMIC, &atomic_ctx)) { ETHQOSERR("Couldn't set SMMU domain as atomic\n"); result = -EIO; goto err_smmu_probe; } ETHQOSDBG("SMMU atomic set\n"); if (iommu_domain_set_attr(emac_emb_smmu_ctx.mapping->domain, DOMAIN_ATTR_FAST, &fast)) { ETHQOSERR("Couldn't set FAST SMMU\n"); result = -EIO; goto err_smmu_probe; } ETHQOSDBG("SMMU fast map set\n"); } result = arm_iommu_attach_device(&emac_emb_smmu_ctx.smmu_pdev->dev, emac_emb_smmu_ctx.mapping); if (result) { ETHQOSERR("couldn't attach to IOMMU ret=%d\n", result); goto err_smmu_probe; } emac_emb_smmu_ctx.iommu_domain = iommu_get_domain_for_dev(&emac_emb_smmu_ctx.smmu_pdev->dev); ETHQOSDBG("Successfully attached to IOMMU\n"); if (emac_emb_smmu_ctx.pdev_master) goto smmu_probe_done; err_smmu_probe: if (emac_emb_smmu_ctx.mapping) arm_iommu_release_mapping(emac_emb_smmu_ctx.mapping); emac_emb_smmu_ctx.valid = false; smmu_probe_done: emac_emb_smmu_ctx.ret = result; return result; } static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; Loading @@ -608,6 +893,15 @@ static int qcom_ethqos_probe(struct platform_device *pdev) struct resource *res; int ret; ipc_emac_log_ctxt = ipc_log_context_create(IPCLOG_STATE_PAGES, "emac", 0); if (!ipc_emac_log_ctxt) ETHQOSERR("Error creating logging context for emac\n"); else ETHQOSDBG("IPC logging has been enabled for emac\n"); if (of_device_is_compatible(pdev->dev.of_node, "qcom,emac-smmu-embedded")) return emac_emb_smmu_cb_probe(pdev); ret = stmmac_get_platform_resources(pdev, &stmmac_res); if (ret) return ret; Loading Loading @@ -659,6 +953,20 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->pmt = 1; plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); if (of_property_read_bool(pdev->dev.of_node, "qcom,arm-smmu")) { emac_emb_smmu_ctx.pdev_master = pdev; ret = of_platform_populate(pdev->dev.of_node, qcom_ethqos_match, NULL, &pdev->dev); if (ret) ETHQOSERR("Failed to populate EMAC platform\n"); if (emac_emb_smmu_ctx.ret) { ETHQOSERR("smmu probe failed\n"); of_platform_depopulate(&pdev->dev); ret = emac_emb_smmu_ctx.ret; emac_emb_smmu_ctx.ret = 0; } } ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_clk; Loading Loading @@ -686,6 +994,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) } pethqos = ethqos; ethqos_create_debugfs(ethqos); return ret; err_clk: Loading @@ -711,16 +1020,12 @@ static int qcom_ethqos_remove(struct platform_device *pdev) if (phy_intr_en) free_irq(ethqos->phy_intr, ethqos); emac_emb_smmu_exit(); ethqos_disable_regulators(ethqos); return ret; } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por}, { .compatible = "qcom,sdxprairie-ethqos", .data = &emac_v2_3_2_por}, { } }; MODULE_DEVICE_TABLE(of, qcom_ethqos_match); static struct platform_driver qcom_ethqos_driver = { Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h +17 −2 Original line number Diff line number Diff line Loading @@ -12,14 +12,28 @@ #ifndef _DWMAC_QCOM_ETHQOS_H #define _DWMAC_QCOM_ETHQOS_H #include <linux/ipc_logging.h> extern void *ipc_emac_log_ctxt; #define IPCLOG_STATE_PAGES 50 #define __FILENAME__ (strrchr(__FILE__, '/') ? \ strrchr(__FILE__, '/') + 1 : __FILE__) #define DRV_NAME "qcom-ethqos" #define ETHQOSDBG(fmt, args...) \ pr_debug(DRV_NAME " %s:%d " fmt, __func__, ## args) #define ETHQOSERR(fmt, args...) \ pr_err(DRV_NAME " %s:%d " fmt, __func__, ## args) do {\ pr_err(DRV_NAME " %s:%d " fmt, __func__, ## args);\ if (ipc_emac_log_ctxt) { \ ipc_log_string(ipc_emac_log_ctxt, \ "%s: %s[%u]:[emac] ERROR:" fmt, __FILENAME__,\ __func__, __LINE__, ## args); \ } \ } while (0) #define ETHQOSINFO(fmt, args...) \ pr_info(DRV_NAME " %s:%d " fmt, __func__, ## args) #define RGMII_IO_MACRO_CONFIG 0x0 #define SDCC_HC_REG_DLL_CONFIG 0x4 #define SDCC_HC_REG_DDR_CONFIG 0xC Loading Loading @@ -130,6 +144,7 @@ struct qcom_ethqos { unsigned long avb_class_a_intr_cnt; unsigned long avb_class_b_intr_cnt; struct dentry *debugfs_dir; }; struct pps_cfg { Loading
drivers/net/ethernet/stmicro/stmmac/ring_mode.c +6 −6 Original line number Diff line number Diff line Loading @@ -47,10 +47,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) if (nopaged_len > BUF_SIZE_8KiB) { des2 = dma_map_single(priv->device, skb->data, bmax, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data, bmax, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; Loading @@ -69,10 +69,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) else desc = tx_q->dma_tx + entry; des2 = dma_map_single(priv->device, skb->data + bmax, len, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data + bmax, len, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; tx_q->tx_skbuff_dma[entry].len = len; Loading @@ -83,10 +83,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) STMMAC_RING_MODE, 1, true, skb->len); } else { des2 = dma_map_single(priv->device, skb->data, des2 = dma_map_single(GET_MEM_PDEV_DEV, skb->data, nopaged_len, DMA_TO_DEVICE); desc->des2 = cpu_to_le32(des2); if (dma_mapping_error(priv->device, des2)) if (dma_mapping_error(GET_MEM_PDEV_DEV, des2)) return -1; tx_q->tx_skbuff_dma[entry].buf = des2; tx_q->tx_skbuff_dma[entry].len = nopaged_len; Loading
drivers/net/ethernet/stmicro/stmmac/stmmac.h +17 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,23 @@ struct stmmac_priv { #endif }; struct emac_emb_smmu_cb_ctx { bool valid; struct platform_device *pdev_master; struct platform_device *smmu_pdev; struct dma_iommu_mapping *mapping; struct iommu_domain *iommu_domain; u32 va_start; u32 va_size; u32 va_end; int ret; }; extern struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx; #define GET_MEM_PDEV_DEV (emac_emb_smmu_ctx.valid ? \ &emac_emb_smmu_ctx.smmu_pdev->dev : priv->device) int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); extern bool phy_intr_en; Loading