diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c index ae4ca3d59ac4c..fa85188355e82 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c @@ -416,9 +416,13 @@ bool fxgmac_read_mac_subsys_from_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, u32 *subsys, u32 *revid) { - u32 machr = 0, maclr = 0, pcie_cfg_ctrl = PCIE_CFG_CTRL_DEFAULT_VAL; +#ifdef DBG + u32 machr = 0, maclr = 0; +#endif + u32 pcie_cfg_ctrl = PCIE_CFG_CTRL_DEFAULT_VAL; bool succeed = true; if (mac_addr) { +#ifdef DBG machr = readreg(pdata->pAdapter, pdata->base_mem + MACA0HR_FROM_EFUSE); maclr = readreg(pdata->pAdapter, @@ -427,7 +431,7 @@ bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, (machr >> 8) & 0xFF, machr & 0xFF, (maclr >> 24) & 0xFF, (maclr >> 16) & 0xFF, (maclr >> 8) & 0xFF, maclr & 0xFF); - +#endif if (!fxgmac_write_patch_to_efuse(pdata, MACA0HR_FROM_EFUSE, (((u32)mac_addr[0]) << 8) | mac_addr[1])) { @@ -473,10 +477,13 @@ bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, bool fxgmac_write_mac_addr_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr) { +#ifdef DBG u32 machr = 0, maclr = 0; +#endif bool succeed = true; if (mac_addr) { +#ifdef DBG machr = readreg(pdata->pAdapter, pdata->base_mem + MACA0HR_FROM_EFUSE); maclr = readreg(pdata->pAdapter, @@ -485,7 +492,7 @@ bool fxgmac_write_mac_addr_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr) (machr >> 8) & 0xFF, machr & 0xFF, (maclr >> 24) & 0xFF, (maclr >> 16) & 0xFF, (maclr >> 8) & 0xFF, maclr & 0xFF); - +#endif if (!fxgmac_write_patch_to_efuse(pdata, MACA0HR_FROM_EFUSE, (((u32)mac_addr[0]) << 8) | mac_addr[1])) { diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c index 63cbf948cbfa2..5ca25a0e39ff2 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c @@ -21,7 +21,7 @@ static void fxgmac_read_mac_addr(struct fxgmac_pdata *pdata) struct net_device *netdev = pdata->netdev; struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - DPRINTK("read mac from eFuse\n"); + /* DPRINTK("read mac from eFuse\n"); */ /* if efuse have mac addr, use it.if not, use static mac address. */ hw_ops->read_mac_subsys_from_efuse(pdata, pdata->mac_addr, NULL, NULL); @@ -35,10 +35,10 @@ static void fxgmac_default_config(struct fxgmac_pdata *pdata) { pdata->tx_osp_mode = DMA_OSP_ENABLE; pdata->tx_sf_mode = MTL_TSF_ENABLE; - pdata->rx_sf_mode = MTL_RSF_DISABLE; /* MTL_RSF_DISABLE 20210514 */ + pdata->rx_sf_mode = MTL_RSF_ENABLE; /* MTL_RSF_DISABLE 20210514 */ pdata->pblx8 = DMA_PBL_X8_ENABLE; /* DMA_PBL_X8_ENABLE 20210514 */ - pdata->tx_pbl = DMA_PBL_32; - pdata->rx_pbl = DMA_PBL_32; /* DMA_PBL_32 20210514 */ + pdata->tx_pbl = DMA_PBL_16; + pdata->rx_pbl = DMA_PBL_4; /* DMA_PBL_32 20210514 */ pdata->tx_threshold = MTL_TX_THRESHOLD_128; pdata->rx_threshold = MTL_RX_THRESHOLD_128; pdata->tx_pause = 1; @@ -66,8 +66,8 @@ static void fxgmac_default_config(struct fxgmac_pdata *pdata) strscpy(pdata->drv_name, FXGMAC_DRV_NAME, sizeof(pdata->drv_name)); strscpy(pdata->drv_ver, FXGMAC_DRV_VERSION, sizeof(pdata->drv_ver)); - printk("FXGMAC_DRV_NAME:%s, FXGMAC_DRV_VERSION:%s\n", FXGMAC_DRV_NAME, - FXGMAC_DRV_VERSION); + dev_info(pdata->dev, "FXGMAC_DRV_NAME:%s, FXGMAC_DRV_VERSION:%s\n", + FXGMAC_DRV_NAME, FXGMAC_DRV_VERSION); } static void fxgmac_init_all_ops(struct fxgmac_pdata *pdata) @@ -75,7 +75,7 @@ static void fxgmac_init_all_ops(struct fxgmac_pdata *pdata) fxgmac_init_desc_ops(&pdata->desc_ops); fxgmac_init_hw_ops(&pdata->hw_ops); - DPRINTK("register desc_ops and hw ops\n"); + /* DPRINTK("register desc_ops and hw ops\n"); */ } int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg) @@ -152,17 +152,11 @@ int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg) pdata->hw_feat.tx_q_cnt); pdata->tx_q_count = pdata->tx_ring_count; -#if !(FXGMAC_NUM_OF_TX_Q_USED) ret = netif_set_real_num_tx_queues(netdev, pdata->tx_q_count); -#else - ret = netif_set_real_num_tx_queues( - netdev, FXGMAC_NUM_OF_TX_Q_USED /*pdata->tx_q_count*/); -#endif DPRINTK("num_online_cpus:%u, tx_ch_cnt:%u, tx_q_cnt:%u, tx_ring_count:%u\n", num_online_cpus(), pdata->hw_feat.tx_ch_cnt, pdata->hw_feat.tx_q_cnt, pdata->tx_ring_count); - if (ret) { dev_err(pdata->dev, "error setting real tx queue count\n"); return ret; @@ -192,7 +186,7 @@ int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg) netif_get_num_default_rss_queues(), pdata->hw_feat.rx_ch_cnt, pdata->hw_feat.rx_q_cnt, pdata->rx_ring_count); DPRINTK("channel_count:%u, netdev tx channel_num=%u\n", - pdata->channel_count, netdev->num_tx_queues); + pdata->channel_count, netdev->real_num_tx_queues); /* Initialize RSS hash key and lookup table */ #if FXGMAC_RSS_HASH_KEY_LINUX @@ -306,6 +300,8 @@ int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg) pdata->rx_usecs = FXGMAC_INIT_DMA_RX_USECS; pdata->rx_frames = FXGMAC_INIT_DMA_RX_FRAMES; + mutex_init(&pdata->expansion.mutex); + DPRINTK("fxgmac_init callout, ok.\n"); return 0; @@ -320,14 +316,14 @@ static void fxgmac_init_interrupt_scheme(struct fxgmac_pdata *pdata) * otherwise, just roll back to legacy */ vectors = num_online_cpus(); - DPRINTK("num of cpu=%d\n", vectors); if (vectors >= FXGMAC_MAX_DMA_CHANNELS) { /* 0-3 for rx, 4 for tx, 5 for phy */ req_vectors = FXGMAC_MSIX_INT_NUMS; pdata->expansion.msix_entries = kcalloc( req_vectors, sizeof(struct msix_entry), GFP_KERNEL); if (!pdata->expansion.msix_entries) { - DPRINTK("MSIx, kcalloc err for msix entries, rollback to MSI..\n"); + dev_err(pdata->dev, "MSIx, kcalloc err for msix entries, \ + rollback to MSI\n"); goto enable_msi_interrupt; } else { for (i = 0; i < req_vectors; i++) @@ -337,14 +333,14 @@ static void fxgmac_init_interrupt_scheme(struct fxgmac_pdata *pdata) pdata->pdev, pdata->expansion.msix_entries, req_vectors, req_vectors); if (rc < 0) { - DPRINTK("enable MSIx failed,%d.\n", rc); + dev_err(pdata->dev, "enable MSIx failed,%d.\n", rc); req_vectors = 0; /* indicate failure */ } else { req_vectors = rc; } if (req_vectors >= FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX) { - DPRINTK("enable MSIx ok, cpu=%d, vectors=%d.\n", + dev_info(pdata->dev, "enable MSIx ok, cpu=%d,vectors=%d.\n", vectors, req_vectors); pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( @@ -353,21 +349,22 @@ static void fxgmac_init_interrupt_scheme(struct fxgmac_pdata *pdata) FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_MSIX_ENABLED); pdata->per_channel_irq = 1; - pdata->expansion.phy_irq = + pdata->expansion.misc_irq = pdata->expansion .msix_entries[MSI_ID_PHY_OTHER] .vector; return; } else if (req_vectors) { - DPRINTK("enable MSIx with only %d vector, while we need %d, rollback to MSI.\n", - req_vectors, vectors); + dev_err(pdata->dev, "enable MSIx with only %d vector, \ ++ while we need %d, rollback to MSI.\n", ++ req_vectors, vectors); /* roll back to msi */ pci_disable_msix(pdata->pdev); kfree(pdata->expansion.msix_entries); pdata->expansion.msix_entries = NULL; req_vectors = 0; } else { - DPRINTK("enable MSIx failure and clear msix entries.\n"); + dev_err(pdata->dev, "enable MSIx failure and clear msix entries.\n"); /* roll back to msi */ kfree(pdata->expansion.msix_entries); pdata->expansion.msix_entries = NULL; @@ -382,13 +379,13 @@ static void fxgmac_init_interrupt_scheme(struct fxgmac_pdata *pdata) pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( pdata->expansion.int_flags, FXGMAC_FLAG_INTERRUPT_POS, FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_LEGACY_ENABLED); - DPRINTK("enable MSI failure, rollback to LEGACY.\n"); + dev_err(pdata->dev, "dev_err MSI failure, rollback to LEGACY.\n"); } else { pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( pdata->expansion.int_flags, FXGMAC_FLAG_INTERRUPT_POS, FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_MSI_ENABLED); pdata->dev_irq = pdata->pdev->irq; - DPRINTK("enable MSI ok, irq=%d.\n", pdata->pdev->irq); + dev_info(pdata->dev, "enable MSI ok, cpu=%d, irq=%d.\n", vectors, pdata->pdev->irq); } #else pdata = pdata; @@ -417,20 +414,16 @@ int fxgmac_drv_probe(struct device *dev, struct fxgmac_resources *res) pdata->netdev = netdev; pdata->dev_irq = res->irq; - + pdata->msg_enable = NETIF_MSG_DRV; + pdata->expansion.dev_state = FXGMAC_DEV_PROBE; /* default to legacy interrupt */ pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( pdata->expansion.int_flags, FXGMAC_FLAG_INTERRUPT_POS, FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_LEGACY_ENABLED); - pdata->expansion.phy_irq = pdata->dev_irq; + pdata->expansion.misc_irq = pdata->dev_irq; fxgmac_init_interrupt_scheme(pdata); - pdata->expansion.current_state = CURRENT_STATE_INIT; - - pdata->msg_enable = NETIF_MSG_DRV; - DPRINTK("netif msg_enable init to %08x\n", pdata->msg_enable); - pdata->mac_regs = res->addr; pdata->base_mem = res->addr; pdata->mac_regs = pdata->mac_regs + FUXI_MAC_REGS_OFFSET; @@ -451,7 +444,7 @@ int fxgmac_drv_probe(struct device *dev, struct fxgmac_resources *res) } if (netif_msg_drv(pdata)) DPRINTK("fxgamc_drv_prob callout, netdev num_tx_q=%u\n", - netdev->num_tx_queues); + netdev->real_num_tx_queues); #ifdef HAVE_FXGMAC_DEBUG_FS fxgmac_dbg_init(pdata); @@ -715,7 +708,7 @@ void fxgmac_get_all_hw_features(struct fxgmac_pdata *pdata) hw_feat->tc_cnt++; hw_feat->hwfr3 = mac_hfr3; - DPRINTK("HWFR3: %u\n", mac_hfr3); + /* DPRINTK("HWFR3: %u\n", mac_hfr3); */ } void fxgmac_print_all_hw_features(struct fxgmac_pdata *pdata) diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c index 4596d91b6e282..0d7fd5a174113 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c @@ -451,8 +451,11 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, memcpy(&ex_data, data, sizeof(CMD_DATA)); ret = hw_ops->read_efuse_data(pdata, ex_data.val0, &ex_data.val1); - DPRINTK("FXGMAC_EFUSE_READ_REGIONABC, address = 0x%x, val = 0x%x\n", - ex_data.val0, ex_data.val1); + /* + * DPRINTK("FXGMAC_EFUSE_READ_REGIONABC, address = 0x%x, val = 0x%x\n", + * ex_data.val0, + * ex_data.val1); + */ if (ret) { memcpy(data, &ex_data, sizeof(CMD_DATA)); out_total_size = @@ -465,8 +468,11 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, case FXGMAC_EFUSE_WRITE_PATCH_REG: memcpy(&ex_data, data, sizeof(CMD_DATA)); - DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_REG, address = 0x%x, val = 0x%x\n", - ex_data.val0, ex_data.val1); + /* + * DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_REG, address = 0x%x, val = 0x%x\n", + * ex_data.val0, + * ex_data.val1); + */ ret = hw_ops->write_patch_to_efuse(pdata, ex_data.val0, ex_data.val1); break; @@ -475,8 +481,10 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, memcpy(&ex_data, data, sizeof(CMD_DATA)); ret = hw_ops->read_patch_from_efuse(pdata, ex_data.val0, &ex_data.val1); - DPRINTK("FXGMAC_EFUSE_READ_PATCH_REG, address = 0x%x, val = 0x%x\n", - ex_data.val0, ex_data.val1); + /* + * DPRINTK("FXGMAC_EFUSE_READ_PATCH_REG, address = 0x%x, val = 0x%x\n", + * ex_data.val0, ex_data.val1); + */ if (ret) { memcpy(data, &ex_data, sizeof(CMD_DATA)); out_total_size = @@ -492,8 +500,10 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, ret = hw_ops->write_patch_to_efuse_per_index( pdata, ex_data.val0, ex_data.val1, ex_data.val2); - DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX, index = %d, address = 0x%x, val = 0x%x\n", - ex_data.val0, ex_data.val1, ex_data.val2); + /* + * DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX, index = %d, address = 0x%x, val = 0x%x\n", + * ex_data.val0, ex_data.val1, ex_data.val2); + */ break; case FXGMAC_EFUSE_READ_PATCH_PER_INDEX: @@ -501,8 +511,10 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, ret = hw_ops->read_patch_from_efuse_per_index( pdata, ex_data.val0, &ex_data.val1, &ex_data.val2); - DPRINTK("FXGMAC_EFUSE_READ_PATCH_PER_INDEX, address = 0x%x, val = 0x%x\n", - ex_data.val1, ex_data.val2); + /* + * DPRINTK("FXGMAC_EFUSE_READ_PATCH_PER_INDEX, address = 0x%x, val = 0x%x\n", + * ex_data.val1, ex_data.val2); + */ if (ret) { memcpy(data, &ex_data, sizeof(CMD_DATA)); out_total_size = @@ -565,7 +577,7 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, pdata, NULL, &ex_data.val0, NULL); break; - case FXGMAC_GET_GMAC_REG: + case FXGMAC_GET_REG: memcpy(&ex_data, data, sizeof(CMD_DATA)); ex_data.val1 = hw_ops->get_gmac_register( pdata, (u8 *)(pdata->mac_regs + ex_data.val0)); @@ -576,7 +588,7 @@ long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, goto err; break; - case FXGMAC_SET_GMAC_REG: + case FXGMAC_SET_REG: memcpy(&ex_data, data, sizeof(CMD_DATA)); regval = hw_ops->set_gmac_register( pdata, (u8 *)(pdata->mac_regs + ex_data.val0), @@ -697,7 +709,7 @@ static struct file_operations fxgmac_dbg_netdev_ops_fops = { /** * fxgmac_dbg_adapter_init - setup the debugfs directory for the adapter - * @adapter: the adapter that is starting up + * @pdata: board private structure **/ void fxgmac_dbg_adapter_init(struct fxgmac_pdata *pdata) { @@ -719,7 +731,7 @@ void fxgmac_dbg_adapter_init(struct fxgmac_pdata *pdata) /** * fxgmac_dbg_adapter_exit - clear out the adapter's debugfs entries - * @adapter: board private structure + * @pdata: board private structure **/ void fxgmac_dbg_adapter_exit(struct fxgmac_pdata *pdata) { @@ -730,6 +742,7 @@ void fxgmac_dbg_adapter_exit(struct fxgmac_pdata *pdata) /** * fxgmac_dbg_init - start up debugfs for the driver + * @pdata: board private structure **/ void fxgmac_dbg_init(struct fxgmac_pdata *pdata) { @@ -777,6 +790,7 @@ void fxgmac_dbg_init(struct fxgmac_pdata *pdata) /** * fxgmac_dbg_exit - clean out the driver's debugfs entries + * @pdata: board private structure **/ void fxgmac_dbg_exit(struct fxgmac_pdata *pdata) { diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c index 969d84eb44e2a..d523e307820b5 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c @@ -209,8 +209,6 @@ static int fxgmac_alloc_channels(struct fxgmac_pdata *pdata) if (!channel_head) return ret; - netif_dbg(pdata, drv, pdata->netdev, "channel_head=%p\n", channel_head); - tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct fxgmac_ring), GFP_KERNEL); if (!tx_ring) @@ -285,11 +283,6 @@ static int fxgmac_alloc_channels(struct fxgmac_pdata *pdata) if (i < pdata->rx_ring_count) channel->rx_ring = rx_ring++; - - netif_dbg(pdata, drv, pdata->netdev, - "%s: dma_regs=%p, tx_ring=%p, rx_ring=%p\n", - channel->name, channel->dma_regs, channel->tx_ring, - channel->rx_ring); } pdata->channel_head = channel_head; @@ -363,9 +356,56 @@ static int fxgmac_map_rx_buffer(struct fxgmac_pdata *pdata, return 0; } +static void fxgmac_tx_desc_reset(struct fxgmac_desc_data *desc_data) +{ + struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; + + /* Reset the Tx descriptor + * Set buffer 1 (lo) address to zero + * Set buffer 1 (hi) address to zero + * Reset all other control bits (IC, TTSE, B2L & B1L) + * Reset all other control bits (OWN, CTXT, FD, LD, CPC, CIC, etc) + */ + dma_desc->desc0 = 0; + dma_desc->desc1 = 0; + dma_desc->desc2 = 0; + dma_desc->desc3 = 0; + + /* Make sure ownership is written to the descriptor */ + dma_wmb(); +} + +static void fxgmac_tx_desc_init_channel(struct fxgmac_channel *channel) +{ + struct fxgmac_ring *ring = channel->tx_ring; + struct fxgmac_desc_data *desc_data; + int start_index = ring->cur; + unsigned int i; + start_index = start_index; + /* Initialize all descriptors */ + for (i = 0; i < ring->dma_desc_count; i++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, i); + + /* Initialize Tx descriptor */ + fxgmac_tx_desc_reset(desc_data); + } + + ///* Update the total number of Tx descriptors */ + //writereg(ring->dma_desc_count - 1, FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); + + writereg(channel->pdata->pAdapter, channel->pdata->tx_desc_count - 1, FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); + + /* Update the starting address of descriptor ring */ + + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + writereg(channel->pdata->pAdapter, upper_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); + writereg(channel->pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); +} + static void fxgmac_tx_desc_init(struct fxgmac_pdata *pdata) { - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; struct fxgmac_desc_data *desc_data; struct fxgmac_dma_desc *dma_desc; struct fxgmac_channel *channel; @@ -399,13 +439,97 @@ static void fxgmac_tx_desc_init(struct fxgmac_pdata *pdata) ring->dirty = 0; memset(&ring->tx, 0, sizeof(ring->tx)); - hw_ops->tx_desc_init(channel); + fxgmac_tx_desc_init_channel(channel); } } +static void fxgmac_rx_desc_reset(struct fxgmac_pdata *pdata, + struct fxgmac_desc_data *desc_data, + unsigned int index) +{ + struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; + + /* Reset the Rx descriptor + * Set buffer 1 (lo) address to header dma address (lo) + * Set buffer 1 (hi) address to header dma address (hi) + * Set buffer 2 (lo) address to buffer dma address (lo) + * Set buffer 2 (hi) address to buffer dma address (hi) and + * set control bits OWN and INTE + */ + //hdr_dma = desc_data->rx.hdr.dma_base + desc_data->rx.hdr.dma_off; + //buf_dma = desc_data->rx.buf.dma_base + desc_data->rx.buf.dma_off; + dma_desc->desc0 = cpu_to_le32(lower_32_bits(desc_data->rx.buf.dma_base)); + dma_desc->desc1 = cpu_to_le32(upper_32_bits(desc_data->rx.buf.dma_base)); + dma_desc->desc2 = 0;//cpu_to_le32(lower_32_bits(buf_dma)); + dma_desc->desc3 = 0;//cpu_to_le32(upper_32_bits(buf_dma)); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, + RX_NORMAL_DESC3_INTE_POS, + RX_NORMAL_DESC3_INTE_LEN, + 1); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, + RX_NORMAL_DESC3_BUF2V_POS, + RX_NORMAL_DESC3_BUF2V_LEN, + 0); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, + RX_NORMAL_DESC3_BUF1V_POS, + RX_NORMAL_DESC3_BUF1V_LEN, + 1); + + /* Since the Rx DMA engine is likely running, make sure everything + * is written to the descriptor(s) before setting the OWN bit + * for the descriptor + */ + dma_wmb(); + + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, + RX_NORMAL_DESC3_OWN_POS, + RX_NORMAL_DESC3_OWN_LEN, + 1); + + /* Make sure ownership is written to the descriptor */ + dma_wmb(); +} + +static void fxgmac_rx_desc_init_channel(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->rx_ring; + unsigned int start_index = ring->cur; + struct fxgmac_desc_data *desc_data; + unsigned int i; + + + /* Initialize all descriptors */ + for (i = 0; i < ring->dma_desc_count; i++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, i); + + /* Initialize Rx descriptor */ + fxgmac_rx_desc_reset(pdata, desc_data, i); + } + + /* Update the total number of Rx descriptors */ + writereg(pdata->pAdapter, ring->dma_desc_count - 1, FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); + + /* Update the starting address of descriptor ring */ + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + writereg(pdata->pAdapter, upper_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); + writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); + + /* Update the Rx Descriptor Tail Pointer */ + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index + + ring->dma_desc_count - 1); + writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); +} + static void fxgmac_rx_desc_init(struct fxgmac_pdata *pdata) { - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; struct fxgmac_desc_data *desc_data; struct fxgmac_dma_desc *dma_desc; struct fxgmac_channel *channel; @@ -438,7 +562,7 @@ static void fxgmac_rx_desc_init(struct fxgmac_pdata *pdata) ring->cur = 0; ring->dirty = 0; - hw_ops->rx_desc_init(channel); + fxgmac_rx_desc_init_channel(channel); } } @@ -591,7 +715,7 @@ static int fxgmac_map_tx_skb(struct fxgmac_channel *channel, void fxgmac_init_desc_ops(struct fxgmac_desc_ops *desc_ops) { - desc_ops->alloc_channles_and_rings = fxgmac_alloc_channels_and_rings; + desc_ops->alloc_channels_and_rings = fxgmac_alloc_channels_and_rings; desc_ops->free_channels_and_rings = fxgmac_free_channels_and_rings; desc_ops->map_tx_skb = fxgmac_map_tx_skb; desc_ops->map_rx_buffer = fxgmac_map_rx_buffer; diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c index 05aa42f90ad83..9b274213ecf27 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c @@ -251,7 +251,7 @@ static void fxgmac_get_reta(struct fxgmac_pdata *pdata, u32 *indir) { int i, reta_size = FXGMAC_RSS_MAX_TABLE_SIZE; u16 rss_m; -#ifdef FXGMAC_ONE_CHANNLE +#ifdef FXGMAC_ONE_CHANNEL rss_m = FXGMAC_MAX_DMA_CHANNELS; #else rss_m = FXGMAC_MAX_DMA_CHANNELS - @@ -267,10 +267,6 @@ static int fxgmac_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, { struct fxgmac_pdata *pdata = netdev_priv(netdev); - /* ETH_RSS_HASH_TOP __ETH_RSS_HASH(TOP) - * ETH_RSS_HASH_XOR __ETH_RSS_HASH(XOR) - * ETH_RSS_HASH_CRC32 __ETH_RSS_HASH(CRC32) - */ if (hfunc) { *hfunc = ETH_RSS_HASH_TOP; DPRINTK("fxmac, get_rxfh for hash function\n"); @@ -635,7 +631,10 @@ static int fxgmac_set_ringparam(struct net_device *netdev, { struct fxgmac_pdata *pdata = netdev_priv(netdev); struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; + if (pdata->expansion.dev_state != FXGMAC_DEV_START) + return 0; + fxgmac_lock(pdata); DPRINTK("fxmac, set_ringparam callin\n"); pdata->tx_desc_count = ring->tx_pending; @@ -644,8 +643,9 @@ static int fxgmac_set_ringparam(struct net_device *netdev, fxgmac_stop(pdata); fxgmac_free_tx_data(pdata); fxgmac_free_rx_data(pdata); - desc_ops->alloc_channles_and_rings(pdata); + desc_ops->alloc_channels_and_rings(pdata); fxgmac_start(pdata); + fxgmac_unlock(pdata); return 0; } @@ -674,15 +674,131 @@ static void fxgmac_get_wol(struct net_device *netdev, return; } wol->wolopts = pdata->expansion.wol; - DPRINTK("fxmac, get_wol, 0x%x, 0x%x\n", wol->wolopts, - pdata->expansion.wol); + /* DPRINTK("fxmac, get_wol, 0x%x, 0x%x\n", wol->wolopts, pdata->expansion.wol); */ +} + +// only supports four patterns, and patterns will be cleared on every call +static void fxgmac_set_pattern_data(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 ip_addr, i = 0; + u8 type_offset, op_offset, tip_offset; + struct pattern_packet packet; + struct wol_bitmap_pattern pattern[4]; // for WAKE_UCAST, WAKE_BCAST, WAKE_MCAST, WAKE_ARP. + + memset(pattern, 0, sizeof(struct wol_bitmap_pattern) * 4); + + //config ucast + if (pdata->expansion.wol & WAKE_UCAST) { + pattern[i].mask_info[0] = 0x3F; + pattern[i].mask_size = sizeof(pattern[0].mask_info); + memcpy(pattern[i].pattern_info, pdata->mac_addr, ETH_ALEN); + pattern[i].pattern_offset = 0; + i++; + } + + // config bcast + if (pdata->expansion.wol & WAKE_BCAST) { + pattern[i].mask_info[0] = 0x3F; + pattern[i].mask_size = sizeof(pattern[0].mask_info); + memset(pattern[i].pattern_info, 0xFF, ETH_ALEN); + pattern[i].pattern_offset = 0; + i++; + } + + // config mcast + if (pdata->expansion.wol & WAKE_MCAST) { + pattern[i].mask_info[0] = 0x7; + pattern[i].mask_size = sizeof(pattern[0].mask_info); + pattern[i].pattern_info[0] = 0x1; + pattern[i].pattern_info[1] = 0x0; + pattern[i].pattern_info[2] = 0x5E; + pattern[i].pattern_offset = 0; + i++; + } + + // config arp + if (pdata->expansion.wol & WAKE_ARP) { + memset(pattern[i].mask_info, 0, sizeof(pattern[0].mask_info)); + type_offset = offsetof(struct pattern_packet, ar_pro); + pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; + type_offset++; + pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; + op_offset = offsetof(struct pattern_packet, ar_op); + pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; + op_offset++; + pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; + tip_offset = offsetof(struct pattern_packet, ar_tip); + pattern[i].mask_info[tip_offset / 8] |= 1 << tip_offset % 8; + tip_offset++; + pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; + tip_offset++; + pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; + tip_offset++; + pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; + + packet.ar_pro = 0x0 << 8 | 0x08; // arp type is 0x0800, notice that ar_pro and ar_op is big endian + packet.ar_op = 0x1 << 8; // 1 is arp request,2 is arp replay, 3 is rarp request, 4 is rarp replay + ip_addr = fxgmac_get_netdev_ip4addr(pdata); + packet.ar_tip[0] = ip_addr & 0xFF; + packet.ar_tip[1] = (ip_addr >> 8) & 0xFF; + packet.ar_tip[2] = (ip_addr >> 16) & 0xFF; + packet.ar_tip[3] = (ip_addr >> 24) & 0xFF; + memcpy(pattern[i].pattern_info, &packet, MAX_PATTERN_SIZE); + pattern[i].mask_size = sizeof(pattern[0].mask_info); + pattern[i].pattern_offset = 0; + i++; + } + + hw_ops->set_wake_pattern(pdata, pattern, i); +} + +void fxgmac_config_wol(struct fxgmac_pdata *pdata, int en) +{ + /* enable or disable WOL. this function only set wake-up type, and power related configure + * will be in other place, see power management. + */ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + if (!pdata->hw_feat.rwk) { + netdev_err(pdata->netdev, "error configuring WOL - not supported.\n"); + return; + } + + hw_ops->disable_wake_magic_pattern(pdata); + hw_ops->disable_wake_pattern(pdata); + hw_ops->disable_wake_link_change(pdata); + + if (en) { + /* config mac address for rx of magic or ucast */ + hw_ops->set_mac_address(pdata, (u8 *)(pdata->netdev->dev_addr)); + + /* Enable Magic packet */ + if (pdata->expansion.wol & WAKE_MAGIC) { + hw_ops->enable_wake_magic_pattern(pdata); + } + + /* Enable global unicast packet */ + if (pdata->expansion.wol & WAKE_UCAST + || pdata->expansion.wol & WAKE_MCAST + || pdata->expansion.wol & WAKE_BCAST + || pdata->expansion.wol & WAKE_ARP) { + hw_ops->enable_wake_pattern(pdata); + } + + /* Enable ephy link change */ + if ((FXGMAC_WOL_UPON_EPHY_LINK) && (pdata->expansion.wol & WAKE_PHY)) { + hw_ops->enable_wake_link_change(pdata); + } + } + device_set_wakeup_enable(/*pci_dev_to_dev*/(pdata->dev), en); + + DPRINTK("config_wol callout\n"); } static int fxgmac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; int ret; /* currently, we do not support these options */ @@ -729,9 +845,9 @@ static int fxgmac_set_wol(struct net_device *netdev, if (wol->wolopts & WAKE_ARP) pdata->expansion.wol |= WAKE_ARP; - hw_ops->set_pattern_data(pdata); + fxgmac_set_pattern_data(pdata); - hw_ops->config_wol(pdata, (!!(pdata->expansion.wol))); + fxgmac_config_wol(pdata, (!!(pdata->expansion.wol))); DPRINTK("fxmac, set_wol, opt=0x%x, 0x%x\n", wol->wolopts, pdata->expansion.wol); @@ -788,8 +904,11 @@ static int fxgmac_get_link_ksettings(struct net_device *netdev, /* Indicate pause support */ ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); - ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); - ethtool_link_ksettings_add_link_mode(cmd, advertising, Asym_Pause); + hw_ops->read_ephy_reg(pdata, REG_MII_ADVERTISE, ®val); + if (FXGMAC_GET_REG_BITS(regval, PHY_MII_ADVERTISE_PAUSE_POS, PHY_MII_ADVERTISE_PAUSE_LEN)) + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + if (FXGMAC_GET_REG_BITS(regval, PHY_MII_ADVERTISE_ASYPAUSE_POS, PHY_MII_ADVERTISE_ASYPAUSE_LEN)) + ethtool_link_ksettings_add_link_mode(cmd, advertising, Asym_Pause); ethtool_link_ksettings_add_link_mode(cmd, supported, MII); cmd->base.port = PORT_MII; @@ -929,15 +1048,7 @@ static int fxgmac_set_link_ksettings(struct net_device *netdev, } else { pdata->phy_duplex = cmd->base.duplex; pdata->phy_speed = cmd->base.speed; - fxgmac_phy_force_speed(pdata, pdata->phy_speed); - fxgmac_phy_force_duplex(pdata, pdata->phy_duplex); - fxgmac_phy_force_autoneg(pdata, pdata->phy_autoeng); - } - - ret = fxgmac_ephy_soft_reset(pdata); - if (ret) { - printk("%s: ephy soft reset timeout.\n", __func__); - return -ETIMEDOUT; + fxgmac_phy_force_mode(pdata); } return 0; @@ -948,7 +1059,7 @@ static void fxgmac_get_pauseparam(struct net_device *netdev, { struct fxgmac_pdata *pdata = netdev_priv(netdev); - pause->autoneg = 1; + pause->autoneg = pdata->phy_autoeng; pause->rx_pause = pdata->rx_pause; pause->tx_pause = pdata->tx_pause; @@ -963,10 +1074,16 @@ static int fxgmac_set_pauseparam(struct net_device *netdev, struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; unsigned int pre_rx_pause = pdata->rx_pause; unsigned int pre_tx_pause = pdata->tx_pause; + u32 adv; + int ret; + int enable_pause = 0; pdata->rx_pause = pause->rx_pause; pdata->tx_pause = pause->tx_pause; + if (pdata->rx_pause || pdata->tx_pause) + enable_pause = 1; + if (pre_rx_pause != pdata->rx_pause) { hw_ops->config_rx_flow_control(pdata); DPRINTK("fxgmac set pause parameter, rx from %d to %d\n", @@ -978,6 +1095,32 @@ static int fxgmac_set_pauseparam(struct net_device *netdev, pre_tx_pause, pdata->tx_pause); } + if (pause->autoneg) { + ret = hw_ops->read_ephy_reg(pdata, REG_MII_ADVERTISE, &adv); + if (ret < 0) + return -ETIMEDOUT; + adv = FXGMAC_SET_REG_BITS(adv, PHY_MII_ADVERTISE_PAUSE_POS, + PHY_MII_ADVERTISE_PAUSE_LEN, + enable_pause); + adv = FXGMAC_SET_REG_BITS(adv, PHY_MII_ADVERTISE_ASYPAUSE_POS, + PHY_MII_ADVERTISE_ASYPAUSE_LEN, + enable_pause); + ret = hw_ops->write_ephy_reg(pdata, REG_MII_ADVERTISE, adv); + if (ret < 0) { + return -ETIMEDOUT; + } + + ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, &adv); + if (ret < 0) + return -ETIMEDOUT; + adv = FXGMAC_SET_REG_BITS(adv, PHY_CR_RE_AUTOENG_POS, PHY_CR_RE_AUTOENG_LEN, 1); + ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, adv); + if (ret < 0) + return -ETIMEDOUT; + } else { + DPRINTK("Can't set phy pause because autoneg is off.\n"); + } + DPRINTK("fxgmac set pause parameter, autoneg=%d, rx=%d, tx=%d\n", pause->autoneg, pause->rx_pause, pause->tx_pause); @@ -1057,6 +1200,47 @@ static inline bool fxgmac_removed(void __iomem *addr) } #define FXGMAC_REMOVED(a) fxgmac_removed(a) +static int fxgmac_ethtool_reset(struct net_device *netdev, u32 *flag) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 val; + + val = (*flag & ETH_RESET_ALL) || (*flag & ETH_RESET_PHY); + if (!val) { + DPRINTK("Operation not support.\n"); + return -EINVAL; + } + + switch (*flag) { + case ETH_RESET_ALL: + fxgmac_restart_dev(pdata); + *flag = 0; + break; + case ETH_RESET_PHY: + /* + * power off and on the phy in order to properly + * configure the MAC timing + */ + hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, &val); + val = FXGMAC_SET_REG_BITS(val, PHY_CR_POWER_POS, + PHY_CR_POWER_LEN, + PHY_POWER_DOWN); + hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, val); + usleep_range_ex(pdata->pAdapter, 9000, 10000); + val = FXGMAC_SET_REG_BITS(val, PHY_CR_POWER_POS, + PHY_CR_POWER_LEN, + PHY_POWER_UP); + hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, val); + *flag = 0; + break; + default: + break; + } + + return 0; +} + static const struct ethtool_ops fxgmac_ethtool_ops = { .get_drvinfo = fxgmac_ethtool_get_drvinfo, .get_link = ethtool_op_get_link, @@ -1065,6 +1249,7 @@ static const struct ethtool_ops fxgmac_ethtool_ops = { .get_channels = fxgmac_ethtool_get_channels, .get_coalesce = fxgmac_ethtool_get_coalesce, .set_coalesce = fxgmac_ethtool_set_coalesce, + .reset = fxgmac_ethtool_reset, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) /* The process of set is to get first and then set, diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c index 0517968365d74..5d0f0034de4d7 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c @@ -12,9 +12,6 @@ static void fxgmac_pwr_clock_gate(struct fxgmac_pdata *pdata); static int fxgmac_tx_complete(struct fxgmac_dma_desc *dma_desc) { -#if (FXGMAC_DUMMY_TX_DEBUG) - return 1; -#endif return !FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, TX_NORMAL_DESC3_OWN_LEN); } @@ -317,7 +314,7 @@ static int fxgmac_set_promiscuous_mode(struct fxgmac_pdata *pdata, if (enable) { fxgmac_disable_rx_vlan_filtering(pdata); } else { - if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (FXGMAC_RX_VLAN_FILTERING) { fxgmac_enable_rx_vlan_filtering(pdata); } } @@ -560,7 +557,7 @@ static int fxgmac_config_jumbo(struct fxgmac_pdata *pdata) static void fxgmac_config_checksum_offload(struct fxgmac_pdata *pdata) { - if (pdata->netdev->features & NETIF_F_RXCSUM) + if (FXGMAC_RX_CHECKSUM) fxgmac_enable_rx_csum(pdata); else fxgmac_disable_rx_csum(pdata); @@ -587,11 +584,10 @@ static void fxgmac_config_vlan_support(struct fxgmac_pdata *pdata) static int fxgmac_config_rx_mode(struct fxgmac_pdata *pdata) { - struct net_device *netdev = pdata->netdev; unsigned int pr_mode, am_mode; - pr_mode = ((netdev->flags & IFF_PROMISC) != 0); - am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); + pr_mode = FXGMAC_NETDEV_PR_MODE; + am_mode = FXGMAC_NETDEV_AM_MODE; fxgmac_set_promiscuous_mode(pdata, pr_mode); fxgmac_set_all_multicast_mode(pdata, am_mode); @@ -604,6 +600,7 @@ static int fxgmac_config_rx_mode(struct fxgmac_pdata *pdata) static void fxgmac_prepare_tx_stop(struct fxgmac_pdata *pdata, struct fxgmac_channel *channel) { +#ifdef FXGMAC_WAIT_TX_STOP unsigned int tx_dsr, tx_pos, tx_qidx; unsigned long tx_timeout; unsigned int tx_status; @@ -643,6 +640,10 @@ static void fxgmac_prepare_tx_stop(struct fxgmac_pdata *pdata, netdev_info(pdata->netdev, "timed out waiting for Tx DMA channel %u to stop\n", channel->queue_index); +#else + pdata = pdata; + channel = channel; +#endif } static void fxgmac_enable_tx(struct fxgmac_pdata *pdata) @@ -775,6 +776,7 @@ static void fxgmac_prepare_rx_stop(struct fxgmac_pdata *pdata, unsigned int queue) { unsigned int rx_status, prxq; +#if defined(FXGMAC_WAIT_RX_STOP_BY_PRXQ_RXQSTS) unsigned int rxqsts; unsigned long rx_timeout; /* The Rx engine cannot be stopped if it is actively processing @@ -804,6 +806,19 @@ static void fxgmac_prepare_rx_stop(struct fxgmac_pdata *pdata, netdev_info(pdata->netdev, "timed out waiting for Rx queue %u to empty\n", queue); +#else + unsigned int busy = 100; + do { + rx_status = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR)); + prxq = FXGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_PRXQ_POS, MTL_Q_RQDR_PRXQ_LEN); + busy--; + usleep_range_ex(pdata->pAdapter, 500, 1000); + } while ((prxq) && (busy)); + if (0 == busy) { + rx_status = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR)); + DbgPrintF(MP_WARN, "warning !!!timed out waiting for Rx queue %u to empty\n", queue); + } +#endif } static void fxgmac_enable_rx(struct fxgmac_pdata *pdata) @@ -953,471 +968,6 @@ static void fxgmac_disable_rx(struct fxgmac_pdata *pdata) #endif } -static void fxgmac_tx_start_xmit(struct fxgmac_channel *channel, - struct fxgmac_ring *ring) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_desc_data *desc_data; - - /* Make sure everything is written before the register write */ - wmb(); - - /* Issue a poll command to Tx DMA by writing address - * of next immediate free descriptor - */ - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); - -#if !(FXGMAC_DUMMY_TX_DEBUG) - writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)); -#else - DPRINTK("dummy tx, fxgmac_tx_start_xmit, tail reg=0x%lx, val=%08x\n", - FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO) - pdata->mac_regs, - (u32)lower_32_bits(desc_data->dma_desc_addr)); -#endif - if (netif_msg_tx_done(pdata)) - DPRINTK("tx_start_xmit: dump before wr reg, dma base=0x%016llx, reg=0x%08x, tx timer usecs=%u, tx_timer_active=%u\n", - desc_data->dma_desc_addr, - readreg(pdata->pAdapter, - FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)), - pdata->tx_usecs, channel->tx_timer_active); - - ring->tx.xmit_more = 0; -} - -static void fxgmac_dev_xmit(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->tx_ring; - unsigned int tso_context, vlan_context; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_pkt_info *pkt_info; - unsigned int csum, tso, vlan; - int start_index = ring->cur; - int cur_index = ring->cur; - int i; - - if (netif_msg_tx_done(pdata)) - DPRINTK("dev_xmit callin, desc cur=%d\n", cur_index); - - pkt_info = &ring->pkt_info; - csum = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN); - tso = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN); - vlan = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN); - - if (tso && (pkt_info->mss != ring->tx.cur_mss)) - tso_context = 1; - else - tso_context = 0; - - if ((tso_context) && (netif_msg_tx_done(pdata))) { - /* tso is initialized to start... */ - DPRINTK("fxgmac_dev_xmit, tso_%s tso=0x%x, pkt_mss=%d, cur_mss=%d\n", - (pkt_info->mss) ? "start" : "stop", tso, pkt_info->mss, - ring->tx.cur_mss); - } - - if (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag)) - vlan_context = 1; - else - vlan_context = 0; - - if (vlan && (netif_msg_tx_done(pdata))) - DPRINTK("fxgmac_dev_xmi:pkt vlan=%d, ring vlan=%d, vlan_context=%d\n", - pkt_info->vlan_ctag, ring->tx.cur_vlan_ctag, - vlan_context); - - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - dma_desc = desc_data->dma_desc; - - /* Create a context descriptor if this is a TSO pkt_info */ - if (tso_context || vlan_context) { - if (tso_context) { - if (netif_msg_tx_done(pdata)) - DPRINTK("xlgamc dev xmit, construct tso context descriptor, mss=%u\n", - pkt_info->mss); - - /* Set the MSS size */ - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, TX_CONTEXT_DESC2_MSS_POS, - TX_CONTEXT_DESC2_MSS_LEN, pkt_info->mss); - - /* Mark it as a CONTEXT descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_CONTEXT_DESC3_CTXT_POS, - TX_CONTEXT_DESC3_CTXT_LEN, 1); - - /* Indicate this descriptor contains the MSS */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_CONTEXT_DESC3_TCMSSV_POS, - TX_CONTEXT_DESC3_TCMSSV_LEN, 1); - - ring->tx.cur_mss = pkt_info->mss; - } - - if (vlan_context) { - netif_dbg(pdata, tx_queued, pdata->netdev, - "VLAN context descriptor, ctag=%u\n", - pkt_info->vlan_ctag); - - /* Mark it as a CONTEXT descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_CONTEXT_DESC3_CTXT_POS, - TX_CONTEXT_DESC3_CTXT_LEN, 1); - - /* Set the VLAN tag */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_CONTEXT_DESC3_VT_POS, - TX_CONTEXT_DESC3_VT_LEN, pkt_info->vlan_ctag); - - /* Indicate this descriptor contains the VLAN tag */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_CONTEXT_DESC3_VLTV_POS, - TX_CONTEXT_DESC3_VLTV_LEN, 1); - - ring->tx.cur_vlan_ctag = pkt_info->vlan_ctag; - } - - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - dma_desc = desc_data->dma_desc; - } - - /* Update buffer address (for TSO this is the header) */ - dma_desc->desc0 = cpu_to_le32(lower_32_bits(desc_data->skb_dma)); - dma_desc->desc1 = cpu_to_le32(upper_32_bits(desc_data->skb_dma)); - - /* Update the buffer length */ - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc2, - TX_NORMAL_DESC2_HL_B1L_POS, - TX_NORMAL_DESC2_HL_B1L_LEN, - desc_data->skb_dma_len); - - /* VLAN tag insertion check */ - if (vlan) { - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, TX_NORMAL_DESC2_VTIR_POS, - TX_NORMAL_DESC2_VTIR_LEN, TX_NORMAL_DESC2_VLAN_INSERT); - pdata->stats.tx_vlan_packets++; - } - - /* Timestamp enablement check */ - if (FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_PTP_POS, - TX_PACKET_ATTRIBUTES_PTP_LEN)) - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, TX_NORMAL_DESC2_TTSE_POS, - TX_NORMAL_DESC2_TTSE_LEN, 1); - - /* Mark it as First Descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_FD_POS, - TX_NORMAL_DESC3_FD_LEN, 1); - - /* Mark it as a NORMAL descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_CTXT_POS, - TX_NORMAL_DESC3_CTXT_LEN, 0); - - /* Set OWN bit if not the first descriptor */ - if (cur_index != start_index) - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN, 1); - - if (tso) { - /* Enable TSO */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_TSE_POS, - TX_NORMAL_DESC3_TSE_LEN, 1); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_TCPPL_POS, - TX_NORMAL_DESC3_TCPPL_LEN, pkt_info->tcp_payload_len); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_TCPHDRLEN_POS, - TX_NORMAL_DESC3_TCPHDRLEN_LEN, - pkt_info->tcp_header_len / 4); - - pdata->stats.tx_tso_packets++; - } else { - /* Enable CRC and Pad Insertion */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_CPC_POS, - TX_NORMAL_DESC3_CPC_LEN, 0); - - /* Enable HW CSUM */ - if (csum) - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_CIC_POS, - TX_NORMAL_DESC3_CIC_LEN, 0x3); - - /* Set the total length to be transmitted */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_FL_POS, - TX_NORMAL_DESC3_FL_LEN, - pkt_info->length); - } - if (netif_msg_tx_done(pdata)) - DPRINTK("dev_xmit before more descs, desc cur=%d, start=%d, desc=%#x,%#x,%#x,%#x\n", - cur_index, start_index, dma_desc->desc0, - dma_desc->desc1, dma_desc->desc2, dma_desc->desc3); - - if (start_index <= cur_index) - i = cur_index - start_index + 1; - else - i = ring->dma_desc_count - start_index + cur_index; - - for (; i < pkt_info->desc_count; i++) { - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - dma_desc = desc_data->dma_desc; - - /* Update buffer address */ - dma_desc->desc0 = - cpu_to_le32(lower_32_bits(desc_data->skb_dma)); - dma_desc->desc1 = - cpu_to_le32(upper_32_bits(desc_data->skb_dma)); - - /* Update the buffer length */ - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, TX_NORMAL_DESC2_HL_B1L_POS, - TX_NORMAL_DESC2_HL_B1L_LEN, desc_data->skb_dma_len); - - /* Set OWN bit */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN, 1); - - /* Mark it as NORMAL descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_CTXT_POS, - TX_NORMAL_DESC3_CTXT_LEN, 0); - - /* Enable HW CSUM */ - if (csum) - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, TX_NORMAL_DESC3_CIC_POS, - TX_NORMAL_DESC3_CIC_LEN, 0x3); - } - - /* Set LAST bit for the last descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_LD_POS, - TX_NORMAL_DESC3_LD_LEN, 1); - - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc2, - TX_NORMAL_DESC2_IC_POS, - TX_NORMAL_DESC2_IC_LEN, 1); - - /* Save the Tx info to report back during cleanup */ - desc_data->tx.packets = pkt_info->tx_packets; - desc_data->tx.bytes = pkt_info->tx_bytes; - - if (netif_msg_tx_done(pdata)) - DPRINTK("dev_xmit last descs, desc cur=%d, desc=%#x,%#x,%#x,%#x\n", - cur_index, dma_desc->desc0, dma_desc->desc1, - dma_desc->desc2, dma_desc->desc3); - - /* In case the Tx DMA engine is running, make sure everything - * is written to the descriptor(s) before setting the OWN bit - * for the first descriptor - */ - dma_wmb(); - - /* Set OWN bit for the first descriptor */ - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - dma_desc = desc_data->dma_desc; - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN, 1); - - if (netif_msg_tx_done(pdata)) - DPRINTK("dev_xmit first descs, start=%d, desc=%#x,%#x,%#x,%#x\n", - start_index, dma_desc->desc0, dma_desc->desc1, - dma_desc->desc2, dma_desc->desc3); - - if (netif_msg_tx_queued(pdata)) - fxgmac_dump_tx_desc(pdata, ring, start_index, - pkt_info->desc_count, 1); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) - if (netif_msg_tx_done(pdata)) - DPRINTK("dev_xmit about to call tx_start_xmit, ring xmit_more=%d, txq_stopped=%x\n", - ring->tx.xmit_more, - netif_xmit_stopped(netdev_get_tx_queue( - pdata->netdev, channel->queue_index))); -#else /* ( LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,165))*/ - if (netif_msg_tx_done(pdata)) - DPRINTK("dev_xmit about to call tx_start_xmit, pkt xmit_more=%d, txq_stopped=%x\n", - pkt_info->skb->xmit_more, - netif_xmit_stopped(netdev_get_tx_queue( - pdata->netdev, channel->queue_index))); -#endif - - /* Make sure ownership is written to the descriptor */ - smp_wmb(); - - ring->cur = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - - fxgmac_tx_start_xmit(channel, ring); - - /* yzhang for reduce debug output */ - if (netif_msg_tx_done(pdata)) { - DPRINTK("dev_xmit callout %s: descriptors %u to %u written\n", - channel->name, start_index & (ring->dma_desc_count - 1), - (ring->cur - 1) & (ring->dma_desc_count - 1)); - } -} - -static void fxgmac_get_rx_tstamp(struct fxgmac_pkt_info *pkt_info, - struct fxgmac_dma_desc *dma_desc) -{ - u64 nsec; - - nsec = le32_to_cpu(dma_desc->desc1); - nsec <<= 32; - nsec |= le32_to_cpu(dma_desc->desc0); - if (nsec != 0xffffffffffffffffULL) { - pkt_info->rx_tstamp = nsec; - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS, - RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN, 1); - } -} - -static void fxgmac_tx_desc_reset(struct fxgmac_desc_data *desc_data) -{ - struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; - - /* Reset the Tx descriptor - * Set buffer 1 (lo) address to zero - * Set buffer 1 (hi) address to zero - * Reset all other control bits (IC, TTSE, B2L & B1L) - * Reset all other control bits (OWN, CTXT, FD, LD, CPC, CIC, etc) - */ - dma_desc->desc0 = 0; - dma_desc->desc1 = 0; - dma_desc->desc2 = 0; - dma_desc->desc3 = 0; - - /* Make sure ownership is written to the descriptor */ - dma_wmb(); -} - -static void fxgmac_tx_desc_init(struct fxgmac_channel *channel) -{ - struct fxgmac_ring *ring = channel->tx_ring; - struct fxgmac_desc_data *desc_data; - int start_index = ring->cur; - unsigned int i; - start_index = start_index; - - /* Initialize all descriptors */ - for (i = 0; i < ring->dma_desc_count; i++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, i); - - /* Initialize Tx descriptor */ - fxgmac_tx_desc_reset(desc_data); - } - - writereg(channel->pdata->pAdapter, channel->pdata->tx_desc_count - 1, - FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); - - /* Update the starting address of descriptor ring */ - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - writereg(channel->pdata->pAdapter, - upper_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); - writereg(channel->pdata->pAdapter, - lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); -} - -static void fxgmac_rx_desc_reset(struct fxgmac_pdata *pdata, - struct fxgmac_desc_data *desc_data, - unsigned int index) -{ - struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; - - /* Reset the Rx descriptor - * Set buffer 1 (lo) address to header dma address (lo) - * Set buffer 1 (hi) address to header dma address (hi) - * Set buffer 2 (lo) address to buffer dma address (lo) - * Set buffer 2 (hi) address to buffer dma address (hi) and - * set control bits OWN and INTE - */ - dma_desc->desc0 = - cpu_to_le32(lower_32_bits(desc_data->rx.buf.dma_base)); - dma_desc->desc1 = - cpu_to_le32(upper_32_bits(desc_data->rx.buf.dma_base)); - dma_desc->desc2 = 0; - dma_desc->desc3 = 0; - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_INTE_POS, - RX_NORMAL_DESC3_INTE_LEN, 1); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_BUF2V_POS, - RX_NORMAL_DESC3_BUF2V_LEN, 0); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_BUF1V_POS, - RX_NORMAL_DESC3_BUF1V_LEN, 1); - - /* Since the Rx DMA engine is likely running, make sure everything - * is written to the descriptor(s) before setting the OWN bit - * for the descriptor - */ - dma_wmb(); - - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_OWN_POS, - RX_NORMAL_DESC3_OWN_LEN, 1); - - /* Make sure ownership is written to the descriptor */ - dma_wmb(); -} - -static void fxgmac_rx_desc_init(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->rx_ring; - unsigned int start_index = ring->cur; - struct fxgmac_desc_data *desc_data; - unsigned int i; - - /* Initialize all descriptors */ - for (i = 0; i < ring->dma_desc_count; i++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, i); - - /* Initialize Rx descriptor */ - fxgmac_rx_desc_reset(pdata, desc_data, i); - } - - /* Update the total number of Rx descriptors */ - writereg(pdata->pAdapter, ring->dma_desc_count - 1, - FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); - - /* Update the starting address of descriptor ring */ - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - writereg(pdata->pAdapter, upper_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); - writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); - - /* Update the Rx Descriptor Tail Pointer */ - desc_data = FXGMAC_GET_DESC_DATA( - ring, start_index + ring->dma_desc_count - 1); - writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); -} - static int fxgmac_is_context_desc(struct fxgmac_dma_desc *dma_desc) { /* Rx and Tx share CTXT bit, so check TDES3.CTXT bit */ @@ -1661,31 +1211,30 @@ static void fxgmac_config_rx_buffer_size(struct fxgmac_pdata *pdata) static void fxgmac_config_tso_mode(struct fxgmac_pdata *pdata) { + u32 tso; #ifndef DPDK struct fxgmac_channel *channel; unsigned int i; u32 regval; + tso = pdata->hw_feat.tso; channel = pdata->channel_head; for (i = 0; i < pdata->channel_count; i++, channel++) { if (!channel->tx_ring) break; - if (pdata->hw_feat.tso) { - regval = readreg(pdata->pAdapter, - FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_TSE_POS, - DMA_CH_TCR_TSE_LEN, 1); - writereg(pdata->pAdapter, regval, - FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - } + regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_TSE_POS, + DMA_CH_TCR_TSE_LEN, tso); + writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); } #else struct fxgmac_tx_queue *txq; unsigned int i; + tso = pdata->hw_feat.tso; for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { txq = pdata->expansion.eth_dev->data->tx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, TSE, pdata->tx_pbl); + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, TSE, tso); } #endif } @@ -1714,7 +1263,7 @@ static void fxgmac_config_sph_mode(struct fxgmac_pdata *pdata) for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { rxq = pdata->expansion.eth_dev->data->rx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_CR, SPH, pdata->rx_pbl); + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_CR, SPH, 0); } #endif @@ -1809,7 +1358,6 @@ static void fxgmac_config_mtl_mode(struct fxgmac_pdata *pdata) static void fxgmac_config_queue_mapping(struct fxgmac_pdata *pdata) { unsigned int ppq, ppq_extra, prio, prio_queues; - unsigned int queue; unsigned int reg, regval; unsigned int mask; unsigned int i, j; @@ -1817,8 +1365,8 @@ static void fxgmac_config_queue_mapping(struct fxgmac_pdata *pdata) /* Map the MTL Tx Queues to Traffic Classes * Note: Tx Queues >= Traffic Classes */ - queue = 0; - DPRINTK("need to map TXq(%u) to TC\n", queue); + // queue = 0; + // DPRINTK("need to map TXq(%u) to TC\n", queue); /* Map the 8 VLAN priority values to available MTL Rx queues */ prio_queues = @@ -2615,7 +2163,7 @@ static void fxgmac_config_mmc(struct fxgmac_pdata *pdata) regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_CR_POS, MMC_CR_CR_LEN, 1); writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); -#if defined(FUXI_MISC_INT_HANDLE_FEATURE_EN) && FUXI_MISC_INT_HANDLE_FEATURE_EN +#if FUXI_MISC_INT_HANDLE_FEATURE_EN writereg(pdata->pAdapter, 0xffffffff, pdata->mac_regs + MMC_IPCRXINTMASK); #endif @@ -2660,7 +2208,6 @@ static int fxgmac_write_rss_options(struct fxgmac_pdata *pdata) return 0; } -#if !defined(DPDK) static int fxgmac_read_rss_hash_key(struct fxgmac_pdata *pdata, u8 *key_buf) { unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); @@ -2683,7 +2230,6 @@ static int fxgmac_read_rss_hash_key(struct fxgmac_pdata *pdata, u8 *key_buf) return 0; } -#endif static int fxgmac_write_rss_hash_key(struct fxgmac_pdata *pdata) { @@ -2789,6 +2335,7 @@ static int fxgmac_enable_rss(struct fxgmac_pdata *pdata) u32 regval; u32 size = 0; +#ifdef FXGMAC_USE_DEFAULT_RSS_KEY_TBALE int ret; if (!pdata->hw_feat.rss) { @@ -2806,6 +2353,7 @@ static int fxgmac_enable_rss(struct fxgmac_pdata *pdata) if (ret) { return ret; } +#endif regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); @@ -2873,6 +2421,7 @@ static void fxgmac_config_rss(struct fxgmac_pdata *pdata) } } +#if defined(FXGMAC_POWER_MANAGEMENT) static void fxgmac_update_aoe_ipv4addr(struct fxgmac_pdata *pdata, u8 *ip_addr) { unsigned int regval, ipval = 0; @@ -2891,12 +2440,14 @@ static void fxgmac_update_aoe_ipv4addr(struct fxgmac_pdata *pdata, u8 *ip_addr) DPRINTK("%s, covert IP dotted-addr %s to binary 0x%08x ok.\n", __FUNCTION__, ip_addr, cpu_to_be32(ipval)); } else { +#ifdef FXGMAC_AOE_FEATURE_ENABLED /* get ipv4 addr from net device */ ipval = fxgmac_get_netdev_ip4addr(pdata); DPRINTK("%s, Get net device binary IP ok, 0x%08x\n", __FUNCTION__, cpu_to_be32(ipval)); ipval = cpu_to_be32(ipval); +#endif } regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ARP_PROTO_ADDR); @@ -3043,8 +2594,8 @@ static int fxgmac_set_ns_offload(struct fxgmac_pdata *pdata, unsigned int index, return 0; } -static void fxgmac_update_ns_offload_ipv6addr(struct fxgmac_pdata *pdata, - unsigned int param) +#ifdef FXGMAC_NS_OFFLOAD_ENABLED +static void fxgmac_update_ns_offload_ipv6addr(struct fxgmac_pdata *pdata, unsigned int param) { struct net_device *netdev = pdata->netdev; unsigned char addr_buf[5][16]; @@ -3084,6 +2635,7 @@ static void fxgmac_update_ns_offload_ipv6addr(struct fxgmac_pdata *pdata, if (pdata->expansion.ns_offload_tab_idx >= 2) pdata->expansion.ns_offload_tab_idx = 0; } +#endif static int fxgmac_enable_ns_offload(struct fxgmac_pdata *pdata) { @@ -3529,7 +3081,7 @@ static int fxgmac_disable_wake_magic_pattern(struct fxgmac_pdata *pdata) return 0; } -#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN +#if FUXI_PM_WPI_READ_FEATURE_EN /* * enable Wake packet indication. called to enable before sleep/hibernation * and no needed to call disable for that, fxgmac_get_wake_packet_indication will clear to normal once done. @@ -3734,51 +3286,9 @@ static int fxgmac_disable_wake_link_change(struct fxgmac_pdata *pdata) writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); return 0; } +#endif // FXGMAC_POWER_MANAGEMENT -static void fxgmac_config_wol(struct fxgmac_pdata *pdata, int en) -{ - /* enable or disable WOL. this function only set wake-up type, and power related configure - * will be in other place, see power management. - */ - if (!pdata->hw_feat.rwk) { - netdev_err(pdata->netdev, - "error configuring WOL - not supported.\n"); - return; - } - - fxgmac_disable_wake_magic_pattern(pdata); - fxgmac_disable_wake_pattern(pdata); - fxgmac_disable_wake_link_change(pdata); - - if (en) { - /* config mac address for rx of magic or ucast */ - fxgmac_set_mac_address(pdata, (u8 *)(pdata->netdev->dev_addr)); - - /* Enable Magic packet */ - if (pdata->expansion.wol & WAKE_MAGIC) { - fxgmac_enable_wake_magic_pattern(pdata); - } - - /* Enable global unicast packet */ - if (pdata->expansion.wol & WAKE_UCAST || - pdata->expansion.wol & WAKE_MCAST || - pdata->expansion.wol & WAKE_BCAST || - pdata->expansion.wol & WAKE_ARP) { - fxgmac_enable_wake_pattern(pdata); - } - - /* Enable ephy link change */ - if ((FXGMAC_WOL_UPON_EPHY_LINK) && - (pdata->expansion.wol & WAKE_PHY)) { - fxgmac_enable_wake_link_change(pdata); - } - } - device_set_wakeup_enable(/*pci_dev_to_dev*/ (pdata->dev), en); - - DPRINTK("config_wol callout\n"); -} - -static int fxgmac_get_ephy_state(struct fxgmac_pdata *pdata) +static u32 fxgmac_get_ephy_state(struct fxgmac_pdata *pdata) { u32 value; value = readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); @@ -3931,14 +3441,13 @@ static void fxgmac_enable_mac_interrupts(struct fxgmac_pdata *pdata) writereg(pdata->pAdapter, mac_ier, pdata->mac_regs + MAC_IER); - /* Enable all counter interrupts */ regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RIER); regval = FXGMAC_SET_REG_BITS(regval, MMC_RIER_ALL_INTERRUPTS_POS, - MMC_RIER_ALL_INTERRUPTS_LEN, 0xffffffff); + MMC_RIER_ALL_INTERRUPTS_LEN, FXGMAC_MMC_IER_ALL_DEFAULT); writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_RIER); regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TIER); regval = FXGMAC_SET_REG_BITS(regval, MMC_TIER_ALL_INTERRUPTS_POS, - MMC_TIER_ALL_INTERRUPTS_LEN, 0xffffffff); + MMC_TIER_ALL_INTERRUPTS_LEN, FXGMAC_MMC_IER_ALL_DEFAULT); writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_TIER); } @@ -4012,10 +3521,11 @@ static int fxgmac_check_phy_link(struct fxgmac_pdata *pdata, u32 *speed, { u16 link_reg = 0; - struct net_device *netdev = pdata->netdev; - if (netdev->base_addr) { - link_reg = - (u16)(*((u32 *)(netdev->base_addr + MGMT_EPHY_CTRL))); + (void) link_up_wait_to_complete; + if (pdata->base_mem) { + link_reg = (u16)readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); + + pdata->phy_duplex = !!(link_reg&0x4);//need check /* * check register address 0x1004 @@ -4025,6 +3535,7 @@ static int fxgmac_check_phy_link(struct fxgmac_pdata *pdata, u32 *speed, * b[1] ephy_link * b[0] ephy_reset. should be set to 1 before use phy. */ + *link_up = false; if (link_reg & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) { if (link_up) { @@ -4141,11 +3652,14 @@ static int fxgmac_write_ephy_mmd_reg(struct fxgmac_pdata *pdata, u32 reg_id, static void fxgmac_config_flow_control(struct fxgmac_pdata *pdata) { +#ifndef FXGMAC_NOT_REPORT_PHY_FC_CAPABILITY_ENABLED u32 regval = 0; +#endif fxgmac_config_tx_flow_control(pdata); fxgmac_config_rx_flow_control(pdata); +#ifndef FXGMAC_NOT_REPORT_PHY_FC_CAPABILITY_ENABLED fxgmac_read_ephy_reg(pdata, REG_MII_ADVERTISE, ®val); /* set auto negotiation advertisement pause ability */ if (pdata->tx_pause || pdata->rx_pause) { @@ -4169,6 +3683,7 @@ static void fxgmac_config_flow_control(struct fxgmac_pdata *pdata) regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, 1); fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); +#endif } static int fxgmac_set_ephy_autoneg_advertise(struct fxgmac_pdata *pdata, @@ -4420,11 +3935,16 @@ void fxgmac_release_phy(struct fxgmac_pdata *pdata) /* led index use bit0~bit5 */ value = FXGMAC_GET_REG_BITS(value, EFUSE_LED_POS, EFUSE_LED_LEN); fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG2); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, - REG_MII_EXT_ANALOG_CFG2_LED_VALUE); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG8); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, - REG_MII_EXT_ANALOG_CFG8_LED_VALUE); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ANALOG_CFG2_VALUE); + + cfg_r32(pdata, REG_PCI_SUB_VENDOR_ID, &value); + if (TONGFANGID_137D1D05_ADJUST_SI == value) { + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG8); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ANALOG_CFG8_137D1D05_VALUE); + } else { + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG8); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ANALOG_CFG8_VALUE); + } if (EFUSE_LED_COMMON_SOLUTION != value) { fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, @@ -4748,145 +4268,6 @@ static void fxgmac_config_led_under_disable(struct fxgmac_pdata *pdata) } } -extern void fxgmac_diag_get_rx_info(struct fxgmac_channel *channel); - -static int fxgmac_dev_read(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->rx_ring; - struct net_device *netdev = pdata->netdev; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_pkt_info *pkt_info; - unsigned int err, etlt, l34t; - - static unsigned int cnt_incomplete; - - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); - dma_desc = desc_data->dma_desc; - pkt_info = &ring->pkt_info; - - /* Check for data availability */ - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_OWN_POS, - RX_NORMAL_DESC3_OWN_LEN)) { - return 1; - } - - /* Make sure descriptor fields are read after reading the OWN bit */ - dma_rmb(); - - if (netif_msg_rx_status(pdata)) - fxgmac_dump_rx_desc(pdata, ring, ring->cur); - - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_CTXT_POS, - RX_NORMAL_DESC3_CTXT_LEN)) { - /* Timestamp Context Descriptor */ - fxgmac_get_rx_tstamp(pkt_info, dma_desc); - - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_LEN, 1); - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN, 0); - if (netif_msg_rx_status(pdata)) - DPRINTK("dev_read context desc, ch=%s\n", channel->name); - return 0; - } - - /* Normal Descriptor, be sure Context Descriptor bit is off */ - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_LEN, 0); - - /* Get the header length */ - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_FD_POS, - RX_NORMAL_DESC3_FD_LEN)) { - desc_data->rx.hdr_len = FXGMAC_GET_REG_BITS_LE( - dma_desc->desc2, RX_NORMAL_DESC2_HL_POS, - RX_NORMAL_DESC2_HL_LEN); - if (desc_data->rx.hdr_len) - pdata->stats.rx_split_header_packets++; - } - l34t = 0; - - /* Get the pkt_info length */ - desc_data->rx.len = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_PL_POS, - RX_NORMAL_DESC3_PL_LEN); - - if (!FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_LD_POS, - RX_NORMAL_DESC3_LD_LEN)) { - /* Not all the data has been transferred for this pkt_info */ - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, - RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, 1); - cnt_incomplete++; - if ((cnt_incomplete < 2) && netif_msg_rx_status(pdata)) - DPRINTK("dev_read NOT last desc, pkt incomplete yet,%u\n", - cnt_incomplete); - - return 0; - } - if ((cnt_incomplete) && netif_msg_rx_status(pdata)) - DPRINTK("dev_read rx back to normal and incomplete cnt=%u\n", - cnt_incomplete); - cnt_incomplete = 0; /* when back to normal, reset cnt */ - - /* This is the last of the data for this pkt_info */ - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, - RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, 0); - - /* Set checksum done indicator as appropriate */ - if (netdev->features & NETIF_F_RXCSUM) - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, - RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 1); - - /* Check for errors (only valid in last descriptor) */ - err = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_ES_POS, - RX_NORMAL_DESC3_ES_LEN); - etlt = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_ETLT_POS, - RX_NORMAL_DESC3_ETLT_LEN); - if ((err) && netif_msg_rx_status(pdata)) { - DPRINTK("dev_read:head_len=%u, pkt_len=%u, err=%u, etlt=%#x, desc2=0x%08x, desc3=0x%08x\n", - desc_data->rx.hdr_len, desc_data->rx.len, err, etlt, - dma_desc->desc2, dma_desc->desc3); - } - - if (!err || !etlt) { - /* No error if err is 0 or etlt is 0 */ - if ((etlt == 0x4 /*yzhang changed to 0x4, 0x09*/) && - (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) { - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN, 1); - pkt_info->vlan_ctag = FXGMAC_GET_REG_BITS_LE( - dma_desc->desc0, RX_NORMAL_DESC0_OVT_POS, - RX_NORMAL_DESC0_OVT_LEN); - netif_dbg(pdata, rx_status, netdev, "vlan-ctag=%#06x\n", - pkt_info->vlan_ctag); - } - } else { - if (etlt == 0x05 || etlt == 0x06) - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, - RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 0); - else - pkt_info->errors = FXGMAC_SET_REG_BITS( - pkt_info->errors, RX_PACKET_ERRORS_FRAME_POS, - RX_PACKET_ERRORS_FRAME_LEN, 1); - } - - return 0; -} - static int fxgmac_enable_int(struct fxgmac_channel *channel, enum fxgmac_int int_id) { @@ -5085,8 +4466,7 @@ static int fxgmac_dismiss_MAC_DBG_int(struct fxgmac_pdata *pdata) int fxgmac_dismiss_all_int(struct fxgmac_pdata *pdata) { struct fxgmac_channel *channel; - unsigned int i, regval; - struct net_device *netdev = pdata->netdev; + unsigned int i; if (netif_msg_drv(pdata)) { DPRINTK("fxgmac_dismiss_all_int callin\n"); @@ -5102,11 +4482,6 @@ int fxgmac_dismiss_all_int(struct fxgmac_pdata *pdata) fxgmac_dismiss_MAC_LPI_int(pdata); fxgmac_dismiss_MAC_DBG_int(pdata); - /* control module int to PCIe slot */ - if (netdev->base_addr) { - regval = (unsigned int)(*( - (u32 *)(netdev->base_addr + MGMT_INT_CTRL0))); - } return 0; } @@ -5116,11 +4491,16 @@ static void fxgmac_set_interrupt_moderation(struct fxgmac_pdata *pdata) pdata->intr_mod_timer = INT_MOD_IN_US; - time = (pdata->intr_mod) ? pdata->intr_mod_timer : 0; +#if defined(FXGMAC_INTERRUPT_TX_INTERVAL) time = (pdata->intr_mod) ? pdata->tx_usecs : 0; +#else + time = (pdata->intr_mod) ? pdata->intr_mod_timer : 0; +#endif value = FXGMAC_SET_REG_BITS(value, INT_MOD_TX_POS, INT_MOD_TX_LEN, time); +#if defined(FXGMAC_INTERRUPT_RX_INTERVAL) time = (pdata->intr_mod) ? pdata->rx_usecs : 0; +#endif value = FXGMAC_SET_REG_BITS(value, INT_MOD_RX_POS, INT_MOD_RX_LEN, time); writereg(pdata->pAdapter, value, pdata->base_mem + INT_MOD); @@ -5241,10 +4621,18 @@ static void fxgmac_config_dma_bus(struct fxgmac_pdata *pdata) { u32 regval; + //set no fix burst length regval = readreg(pdata->pAdapter, pdata->mac_regs + DMA_SBMR); /* Set enhanced addressing mode */ regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_EAME_POS, DMA_SBMR_EAME_LEN, 1); + + /* Out standing read/write requests*/ + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_RD_OSR_LMT_POS, + DMA_SBMR_RD_OSR_LMT_LEN, 0x7); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_WR_OSR_LMT_POS, + DMA_SBMR_WR_OSR_LMT_LEN, 0x7); + /* Set the System Bus mode */ regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_FB_POS, DMA_SBMR_FB_LEN, 0); @@ -5275,121 +4663,106 @@ static void fxgmac_legacy_link_speed_setting(struct fxgmac_pdata *pdata) NULL); /* clear phy interrupt. */ } -static void fxgmac_pre_powerdown(struct fxgmac_pdata *pdata, bool phyloopback) +#if defined(FXGMAC_FIX_SHUT_DOWN_ISSUE) +static void fxgmac_link_speed_down_fix_shutdown_issue(struct fxgmac_pdata *pdata) { + LONGLONG tick_interval; + ULONG tick_inc; + LARGE_INTEGER tick_count; + unsigned int i = 0; unsigned int regval = 0; + if ((ULONG)pdata->phy_speed != ((PMP_ADAPTER)pdata->pAdapter)->usLinkSpeed) { + DbgPrintF(MP_TRACE, "%s change phy speed", __FUNCTION__); + pdata->phy_speed = ((PMP_ADAPTER)pdata->pAdapter)->usLinkSpeed; + + if (((PMP_ADAPTER)pdata->pAdapter)->RegParameter.LinkChgWol) { + fxgmac_phy_config(pdata); + //sleep fixed value(6s) + for (i = 0; i < PHY_LINK_TIMEOUT; i++) { + usleep_range_ex(pdata->pAdapter, 2000, 2000); + } + + fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); // clear phy interrupt. + } else { + regval = fxgmac_get_ephy_state(pdata); + KeQueryTickCount(&tick_count); + tick_inc = KeQueryTimeIncrement(); + tick_interval = tick_count.QuadPart - ((PMP_ADAPTER)pdata->pAdapter)->D0_entry_tick_count.QuadPart; + tick_interval *= tick_inc; + tick_interval /= 10; + + /*DbgPrintF(MP_TRACE, "base tick %lld", ((PMP_ADAPTER)pdata->pAdapter)->D0_entry_tick_count.QuadPart); + DbgPrintF(MP_TRACE, "current tick %lld", tick_count.QuadPart); + DbgPrintF(MP_TRACE, "tick inc is %u", tick_inc); + DbgPrintF(MP_TRACE, "tick_interval is %lld", tick_interval); + DbgPrintF(MP_TRACE, "regval is 0x%x", regval);*/ + if (((regval & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) && (regval & MGMT_EPHY_CTRL_STA_EPHY_LINKUP)) + || ((regval & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) && !(regval & MGMT_EPHY_CTRL_STA_EPHY_LINKUP) && (tick_interval < RESUME_MAX_TIME)) + ) { + fxgmac_legacy_link_speed_setting(pdata); + } + } + } +} +#endif + +static void fxgmac_pre_powerdown(struct fxgmac_pdata *pdata, bool phyloopback) +{ + u32 regval = 0; + int speed = SPEED_10; + speed = speed; fxgmac_disable_rx(pdata); /* HERE, WE NEED TO CONSIDER PHY CONFIG...TBD */ DPRINTK("fxgmac_config_powerdown, phy and mac status update\n"); - /* for phy cable loopback, it can't configure phy speed, it will cause os resume again by link change although it has finished speed setting, */ + //2022-11-09 xiaojiang comment + //for phy cable loopback,it can't configure phy speed, it will cause os resume again by link change although it has finished speed setting, if (!phyloopback) { - /* When the Linux platform enters the s4 state, it goes through - * the suspend->resume->suspend process. The process of - * suspending again after resume is fast, and PHY - * auto-negotiation is not yet complete, so the - * auto-negotiation of PHY must be carried out again. When the - * Linux platform enters the s4 state, force speed to 10M. - */ - pdata->phy_speed = SPEED_10; + fxgmac_read_ephy_reg(pdata, REG_MII_LPA, ®val); + if (!FXGMAC_GET_REG_BITS(regval, PHY_MII_LINK_PARNTNER_10FULL_POS, PHY_MII_LINK_PARNTNER_10FULL_LEN) + && !FXGMAC_GET_REG_BITS(regval, PHY_MII_LINK_PARNTNER_10HALF_POS, PHY_MII_LINK_PARNTNER_10HALF_LEN)) { + #if defined(FXGMAC_LINK_SPEED_NOT_USE_LOCAL_VARIABLE) + if (SPEED_10 == ((PMP_ADAPTER)pdata->pAdapter)->usLinkSpeed) { + ((PMP_ADAPTER)pdata->pAdapter)->usLinkSpeed = SPEED_100; + } + #else + speed = SPEED_100; + #endif + } + + #if defined(FXGMAC_FIX_SHUT_DOWN_ISSUE) + fxgmac_link_speed_down_fix_shutdown_issue(pdata); + #elif defined(FXGMAC_LINK_SPEED_CHECK_PHY_LINK) + /* + When the Linux platform enters the s4 state, it goes through the suspend->resume->suspend process. + The process of suspending again after resume is fast, and PHY auto-negotiation is not yet complete, + so the auto-negotiation of PHY must be carried out again.Windows platforms and UEFI platforms do + not need to auto-negotiate again, as they will not have such a process. + + When the Linux platform enters the s4 state, force speed to 10M. + */ + if (pdata->expansion.phy_link && (speed != pdata->phy_speed)) { + pdata->phy_speed = speed; + fxgmac_legacy_link_speed_setting(pdata); + } + #else fxgmac_legacy_link_speed_setting(pdata); + #endif } fxgmac_config_mac_speed(pdata); - /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and - * lead to panic sometimes. So we should disable it from powerup, - * enable it from power down. - */ + /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and lead to panic sometimes. + So we should disable it from powerup, enable it from power down.*/ regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + OOB_WOL_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, OOB_WOL_CTRL_DIS_POS, - OOB_WOL_CTRL_DIS_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, OOB_WOL_CTRL_DIS_POS, OOB_WOL_CTRL_DIS_LEN, 0); writereg(pdata->pAdapter, regval, pdata->base_mem + OOB_WOL_CTRL); usleep_range_ex(pdata->pAdapter, 2000, 2000); /* after enable OOB_WOL, recofigure mac addr again */ fxgmac_set_mac_address(pdata, pdata->mac_addr); -} - -/* only supports four patterns, and patterns will be cleared on every call */ -static void fxgmac_set_pattern_data(struct fxgmac_pdata *pdata) -{ - u32 ip_addr, i = 0; - u8 type_offset, op_offset, tip_offset; - struct pattern_packet packet; - struct wol_bitmap_pattern - pattern[4]; /* for WAKE_UCAST, WAKE_BCAST, WAKE_MCAST, WAKE_ARP. */ - - memset(pattern, 0, sizeof(struct wol_bitmap_pattern) * 4); - - /* config ucast */ - if (pdata->expansion.wol & WAKE_UCAST) { - pattern[i].mask_info[0] = 0x3F; - pattern[i].mask_size = sizeof(pattern[0].mask_info); - memcpy(pattern[i].pattern_info, pdata->mac_addr, ETH_ALEN); - pattern[i].pattern_offset = 0; - i++; - } - - /* config bcast */ - if (pdata->expansion.wol & WAKE_BCAST) { - pattern[i].mask_info[0] = 0x3F; - pattern[i].mask_size = sizeof(pattern[0].mask_info); - memset(pattern[i].pattern_info, 0xFF, ETH_ALEN); - pattern[i].pattern_offset = 0; - i++; - } - - /* config mcast */ - if (pdata->expansion.wol & WAKE_MCAST) { - pattern[i].mask_info[0] = 0x7; - pattern[i].mask_size = sizeof(pattern[0].mask_info); - pattern[i].pattern_info[0] = 0x1; - pattern[i].pattern_info[1] = 0x0; - pattern[i].pattern_info[2] = 0x5E; - pattern[i].pattern_offset = 0; - i++; - } - - /* config arp */ - if (pdata->expansion.wol & WAKE_ARP) { - memset(pattern[i].mask_info, 0, sizeof(pattern[0].mask_info)); - type_offset = offsetof(struct pattern_packet, ar_pro); - pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; - type_offset++; - pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; - op_offset = offsetof(struct pattern_packet, ar_op); - pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; - op_offset++; - pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; - tip_offset = offsetof(struct pattern_packet, ar_tip); - pattern[i].mask_info[tip_offset / 8] |= 1 << tip_offset % 8; - tip_offset++; - pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; - tip_offset++; - pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; - tip_offset++; - pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; - - packet.ar_pro = - 0x0 << 8 | - 0x08; /* arp type is 0x0800, notice that ar_pro and ar_op is big endian */ - packet.ar_op = - 0x1 - << 8; /* 1 is arp request,2 is arp replay, 3 is rarp request, 4 is rarp replay */ - ip_addr = fxgmac_get_netdev_ip4addr(pdata); - packet.ar_tip[0] = ip_addr & 0xFF; - packet.ar_tip[1] = (ip_addr >> 8) & 0xFF; - packet.ar_tip[2] = (ip_addr >> 16) & 0xFF; - packet.ar_tip[3] = (ip_addr >> 24) & 0xFF; - memcpy(pattern[i].pattern_info, &packet, MAX_PATTERN_SIZE); - pattern[i].mask_size = sizeof(pattern[0].mask_info); - pattern[i].pattern_offset = 0; - i++; - } - - fxgmac_set_wake_pattern(pdata, pattern, i); + //fxgmac_suspend_clock_gate(pdata); } static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, @@ -5432,13 +4805,6 @@ static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); } - if (!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { - netdev_err( - pdata->netdev, - "fxgmac powerstate is %lu when config power to down.\n", - pdata->expansion.powerstate); - } - #if FXGMAC_WOL_FEATURE_ENABLED fxgmac_config_wol(pdata, wol); #endif @@ -5455,12 +4821,24 @@ static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, fxgmac_enable_ns_offload(pdata); #endif +#if FUXI_PM_WPI_READ_FEATURE_EN + fxgmac_enable_wake_packet_indication(pdata, 1); +#endif + /* Enable MAC Rx TX */ +#ifdef FXGMAC_WOL_INTEGRATED_WOL_PARAMETER if (1) { +#else + if (magic_en || remote_pattern_en || offloadcount) { +#endif regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, MAC_CR_RE_LEN, 1); +#if defined(FXGMAC_AOE_FEATURE_ENABLED) || defined(FXGMAC_NS_OFFLOAD_ENABLED) if (pdata->hw_feat.aoe) { +#else + if (offloadcount) { +#endif regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, MAC_CR_TE_LEN, 1); } @@ -5480,6 +4858,8 @@ static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, MAC_PMT_STA_PWRDWN_LEN, 1); writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); +//#ifdef FXGMAC_FIX_FT_D2000_PLATFORM_WOL_ISSUE +#ifdef ARM64 /* adjust sigdet threshold * redmine.motor-comm.com/issues/5093 * fix issue can not wake up os on some FT-D2000 platform, y @@ -5490,6 +4870,7 @@ static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, regval = FXGMAC_SET_REG_BITS(regval, MGMT_SIGDET_POS, MGMT_SIGDET_LEN, MGMT_SIGDET_40MV); writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_SIGDET); +#endif DPRINTK("fxgmac_config_powerdown callout, reg=0x%08x\n", regval); } @@ -5497,13 +4878,6 @@ static void fxgmac_config_powerup(struct fxgmac_pdata *pdata) { u32 regval = 0; - if (test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { - netdev_err( - pdata->netdev, - "fxgmac powerstate is %lu when config power to up.\n", - pdata->expansion.powerstate); - } - /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and lead to panic sometimes. * So we should disable it from powerup, enable it from power down. */ @@ -5799,10 +5173,10 @@ static int fxgmac_hw_init(struct fxgmac_pdata *pdata) /* Flush Tx queues */ ret = fxgmac_flush_tx_queues(pdata); if (ret) { - if (netif_msg_drv(pdata)) { - DPRINTK("fxgmac_hw_init call flush tx queue err.\n"); - } - return ret; +#ifdef FXGMAC_FLUSH_TX_CHECK_ENABLED + dev_err(pdata->dev, "fxgmac_hw_init call flush tx queue err.\n"); + return ret; +#endif } /* Initialize DMA related features */ @@ -5817,7 +5191,6 @@ static int fxgmac_hw_init(struct fxgmac_pdata *pdata) fxgmac_config_tso_mode(pdata); fxgmac_config_sph_mode(pdata); fxgmac_config_rss(pdata); - fxgmac_config_wol(pdata, pdata->expansion.wol); desc_ops->tx_desc_init(pdata); desc_ops->rx_desc_init(pdata); @@ -5872,6 +5245,29 @@ static void fxgmac_save_nonstick_reg(struct fxgmac_pdata *pdata) pdata->reg_nonstick[(i - REG_PCIE_TRIGGER) >> 2] = readreg(pdata->pAdapter, pdata->base_mem + i); } + cfg_r32(pdata, REG_PCI_COMMAND, &pdata->expansion.cfg_pci_cmd); + cfg_r32(pdata, REG_CACHE_LINE_SIZE, &pdata->expansion.cfg_cache_line_size); + cfg_r32(pdata, REG_MEM_BASE, &pdata->expansion.cfg_mem_base); + cfg_r32(pdata, REG_MEM_BASE_HI, &pdata->expansion.cfg_mem_base_hi); + cfg_r32(pdata, REG_IO_BASE, &pdata->expansion.cfg_io_base); + cfg_r32(pdata, REG_INT_LINE, &pdata->expansion.cfg_int_line); + cfg_r32(pdata, REG_DEVICE_CTRL1, &pdata->expansion.cfg_device_ctrl1); + cfg_r32(pdata, REG_PCI_LINK_CTRL, &pdata->expansion.cfg_pci_link_ctrl); + cfg_r32(pdata, REG_DEVICE_CTRL2, &pdata->expansion.cfg_device_ctrl2); + cfg_r32(pdata, REG_MSIX_CAPABILITY, &pdata->expansion.cfg_msix_capability); + + DbgPrintF(MP_TRACE, "%s:\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\n", + __FUNCTION__, + REG_PCI_COMMAND, pdata->expansion.cfg_pci_cmd, + REG_CACHE_LINE_SIZE, pdata->expansion.cfg_cache_line_size, + REG_MEM_BASE, pdata->expansion.cfg_mem_base, + REG_MEM_BASE_HI, pdata->expansion.cfg_mem_base_hi, + REG_IO_BASE, pdata->expansion.cfg_io_base, + REG_INT_LINE, pdata->expansion.cfg_int_line, + REG_DEVICE_CTRL1, pdata->expansion.cfg_device_ctrl1, + REG_PCI_LINK_CTRL, pdata->expansion.cfg_pci_link_ctrl, + REG_DEVICE_CTRL2, pdata->expansion.cfg_device_ctrl2, + REG_MSIX_CAPABILITY, pdata->expansion.cfg_msix_capability); } static void fxgmac_restore_nonstick_reg(struct fxgmac_pdata *pdata) @@ -5884,6 +5280,7 @@ static void fxgmac_restore_nonstick_reg(struct fxgmac_pdata *pdata) } } +#if defined(FXGMAC_ESD_RESTORE_PCIE_CFG) static void fxgmac_esd_restore_pcie_cfg(struct fxgmac_pdata *pdata) { cfg_w32(pdata, REG_PCI_COMMAND, pdata->expansion.cfg_pci_cmd); @@ -5899,6 +5296,7 @@ static void fxgmac_esd_restore_pcie_cfg(struct fxgmac_pdata *pdata) cfg_w32(pdata, REG_MSIX_CAPABILITY, pdata->expansion.cfg_msix_capability); } +#endif static int fxgmac_hw_exit(struct fxgmac_pdata *pdata) { @@ -5938,21 +5336,21 @@ static int fxgmac_hw_exit(struct fxgmac_pdata *pdata) return 0; } -static int fxgmac_set_gmac_register(struct fxgmac_pdata *pdata, u8 *address, +static int fxgmac_set_gmac_register(struct fxgmac_pdata *pdata, IOMEM address, unsigned int data) { - if (address < (u8 *)(pdata->base_mem)) { + if (address < pdata->base_mem) { return -1; } writereg(pdata->pAdapter, data, address); return 0; } -static u32 fxgmac_get_gmac_register(struct fxgmac_pdata *pdata, u8 *address) +static u32 fxgmac_get_gmac_register(struct fxgmac_pdata *pdata, IOMEM address) { u32 regval = 0; - if (address > (u8 *)(pdata->base_mem)) { + if (address > pdata->base_mem) { regval = readreg(pdata->pAdapter, address); } return regval; @@ -6063,7 +5461,9 @@ void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) hw_ops->exit = fxgmac_hw_exit; hw_ops->save_nonstick_reg = fxgmac_save_nonstick_reg; hw_ops->restore_nonstick_reg = fxgmac_restore_nonstick_reg; +#if defined(FXGMAC_ESD_RESTORE_PCIE_CFG) hw_ops->esd_restore_pcie_cfg = fxgmac_esd_restore_pcie_cfg; +#endif hw_ops->set_gmac_register = fxgmac_set_gmac_register; hw_ops->get_gmac_register = fxgmac_get_gmac_register; @@ -6074,9 +5474,6 @@ void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) hw_ops->enable_rx = fxgmac_enable_rx; hw_ops->disable_rx = fxgmac_disable_rx; hw_ops->enable_channel_rx = fxgmac_enable_channel_rx; - hw_ops->dev_xmit = fxgmac_dev_xmit; - hw_ops->dev_read = fxgmac_dev_read; - hw_ops->config_tso = fxgmac_config_tso_mode; hw_ops->enable_int = fxgmac_enable_int; hw_ops->disable_int = fxgmac_disable_int; hw_ops->set_interrupt_moderation = fxgmac_set_interrupt_moderation; @@ -6088,6 +5485,7 @@ void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) hw_ops->disable_msix_one_interrupt = fxgmac_disable_msix_one_interrupt; hw_ops->enable_mgm_interrupt = fxgmac_enable_mgm_interrupt; hw_ops->disable_mgm_interrupt = fxgmac_disable_mgm_interrupt; + hw_ops->dismiss_all_int = fxgmac_dismiss_all_int; hw_ops->set_mac_address = fxgmac_set_mac_address; hw_ops->set_mac_hash = fxgmac_add_mac_addresses; @@ -6100,17 +5498,10 @@ void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) hw_ops->get_xlgmii_phy_status = fxgmac_check_phy_link; /* For descriptor related operation */ - hw_ops->tx_desc_init = fxgmac_tx_desc_init; - hw_ops->rx_desc_init = fxgmac_rx_desc_init; - hw_ops->tx_desc_reset = fxgmac_tx_desc_reset; - hw_ops->rx_desc_reset = fxgmac_rx_desc_reset; hw_ops->is_last_desc = fxgmac_is_last_desc; hw_ops->is_context_desc = fxgmac_is_context_desc; - hw_ops->tx_start_xmit = fxgmac_tx_start_xmit; - hw_ops->set_pattern_data = fxgmac_set_pattern_data; - hw_ops->config_wol = fxgmac_config_wol; - hw_ops->get_rss_hash_key = fxgmac_read_rss_hash_key; - hw_ops->write_rss_lookup_table = fxgmac_write_rss_lookup_table; + + hw_ops->config_tso = fxgmac_config_tso_mode; #if FXGMAC_SANITY_CHECK_ENABLED hw_ops->diag_sanity_check = fxgmac_diag_sanity_check; #endif @@ -6167,8 +5558,11 @@ void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) hw_ops->set_rss_options = fxgmac_write_rss_options; hw_ops->set_rss_hash_key = fxgmac_set_rss_hash_key; hw_ops->set_rss_lookup_table = fxgmac_set_rss_lookup_table; + hw_ops->get_rss_hash_key = fxgmac_read_rss_hash_key; + hw_ops->write_rss_lookup_table = fxgmac_write_rss_lookup_table; - /*For Offload*/ + /*For Power Management*/ +#if defined(FXGMAC_POWER_MANAGEMENT) hw_ops->set_arp_offload = fxgmac_update_aoe_ipv4addr; hw_ops->enable_arp_offload = fxgmac_enable_arp_offload; hw_ops->disable_arp_offload = fxgmac_disable_arp_offload; @@ -6189,10 +5583,11 @@ void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) hw_ops->enable_wake_pattern = fxgmac_enable_wake_pattern; hw_ops->disable_wake_pattern = fxgmac_disable_wake_pattern; hw_ops->set_wake_pattern_mask = fxgmac_set_wake_pattern_mask; -#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN +#if FUXI_PM_WPI_READ_FEATURE_EN hw_ops->enable_wake_packet_indication = fxgmac_enable_wake_packet_indication; hw_ops->get_wake_packet_indication = fxgmac_get_wake_packet_indication; +#endif #endif /*For phy write /read*/ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c index b8734efb36426..305a46a0afaf1 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c @@ -16,6 +16,143 @@ static int fxgmac_one_poll_rx(struct napi_struct *, int); static int fxgmac_one_poll_tx(struct napi_struct *, int); static int fxgmac_all_poll(struct napi_struct *, int); +void fxgmac_lock(struct fxgmac_pdata *pdata) +{ + mutex_lock(&pdata->expansion.mutex); +} + +void fxgmac_unlock(struct fxgmac_pdata *pdata) +{ + mutex_unlock(&pdata->expansion.mutex); +} + +#ifdef FXGMAC_ESD_CHECK_ENABLED +static void fxgmac_schedule_esd_work(struct fxgmac_pdata *pdata) +{ + set_bit(FXGMAC_FLAG_TASK_ESD_CHECK_PENDING, pdata->expansion.task_flags); + schedule_delayed_work(&pdata->expansion.esd_work, FXGMAC_ESD_INTERVAL); +} + +static void fxgmac_update_esd_stats(struct fxgmac_pdata *pdata) +{ + u32 value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXEXCESSIVECOLLSIONFRAMES); + pdata->expansion.esd_stats.tx_abort_excess_collisions += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXUNDERFLOWERROR_LO); + pdata->expansion.esd_stats.tx_dma_underrun += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXCARRIERERRORFRAMES); + pdata->expansion.esd_stats.tx_lost_crs += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXLATECOLLISIONFRAMES); + pdata->expansion.esd_stats.tx_late_collisions += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RXCRCERROR_LO); + pdata->expansion.esd_stats.rx_crc_errors += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RXALIGNERROR); + pdata->expansion.esd_stats.rx_align_errors += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RXRUNTERROR); + pdata->expansion.esd_stats.rx_runt_errors += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXSINGLECOLLISION_G); + pdata->expansion.esd_stats.single_collisions += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXMULTIPLECOLLISION_G); + pdata->expansion.esd_stats.multi_collisions += value; + + value = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TXDEFERREDFRAMES); + pdata->expansion.esd_stats.tx_deferred_frames += value; +} + +static void fxgmac_check_esd_work(struct fxgmac_pdata *pdata) +{ + FXGMAC_ESD_STATS *stats = &pdata->expansion.esd_stats; + int i = 0; + u32 regval; + + /* ESD test will make recv crc errors more than 4,294,967,xxx in one second. */ + if (stats->rx_crc_errors > FXGMAC_ESD_ERROR_THRESHOLD || + stats->rx_align_errors > FXGMAC_ESD_ERROR_THRESHOLD || + stats->rx_runt_errors > FXGMAC_ESD_ERROR_THRESHOLD || + stats->tx_abort_excess_collisions > FXGMAC_ESD_ERROR_THRESHOLD || + stats->tx_dma_underrun > FXGMAC_ESD_ERROR_THRESHOLD || + stats->tx_lost_crs > FXGMAC_ESD_ERROR_THRESHOLD || + stats->tx_late_collisions > FXGMAC_ESD_ERROR_THRESHOLD || + stats->single_collisions > FXGMAC_ESD_ERROR_THRESHOLD || + stats->multi_collisions > FXGMAC_ESD_ERROR_THRESHOLD || + stats->tx_deferred_frames > FXGMAC_ESD_ERROR_THRESHOLD) { + dev_info(pdata->dev, "%s - Error:\n", __func__); + dev_info(pdata->dev, "rx_crc_errors %ul.\n", stats->rx_crc_errors); + dev_info(pdata->dev, "rx_align_errors %ul.\n", stats->rx_align_errors); + dev_info(pdata->dev, "rx_runt_errors %ul.\n", stats->rx_runt_errors); + dev_info(pdata->dev, "tx_abort_excess_collisions %ul.\n", stats->tx_abort_excess_collisions); + dev_info(pdata->dev, "tx_dma_underrun %ul.\n", stats->tx_dma_underrun); + dev_info(pdata->dev, "tx_lost_crs %ul.\n", stats->tx_lost_crs); + dev_info(pdata->dev, "tx_late_collisions %ul.\n", stats->tx_late_collisions); + dev_info(pdata->dev, "single_collisions %ul.\n", stats->single_collisions); + dev_info(pdata->dev, "multi_collisions %ul.\n", stats->multi_collisions); + dev_info(pdata->dev, "tx_deferred_frames %ul.\n", stats->tx_deferred_frames); + + dev_info(pdata->dev, "esd error triggered, restart NIC...\n"); + cfg_r32(pdata, REG_PCI_COMMAND, ®val); + while ((regval == FXGMAC_PCIE_LINK_DOWN) && (i++ < FXGMAC_PCIE_RECOVER_TIMES)) { + usleep_range_ex(pdata->pAdapter, 200, 200); + cfg_r32(pdata, REG_PCI_COMMAND, ®val); + dev_info(pdata->dev, "pcie recovery link cost %d(200us)\n", i); + } + + if (regval == FXGMAC_PCIE_LINK_DOWN) { + dev_info(pdata->dev, "pcie link down, recovery failed.\n"); + return; + } + + if (regval & FXGMAC_PCIE_IO_MEM_MASTER_ENABLE) { + pdata->hw_ops.esd_restore_pcie_cfg(pdata); + cfg_r32(pdata, REG_PCI_COMMAND, ®val); + dev_info(pdata->dev, "pci command reg is %x after restoration.\n", regval); + fxgmac_restart_dev(pdata); + } + } + + memset(stats, 0, sizeof(FXGMAC_ESD_STATS)); +} + +static void fxgmac_esd_work(struct work_struct *work) +{ + struct fxgmac_pdata *pdata = container_of(work, + struct fxgmac_pdata, + expansion.esd_work.work); + + rtnl_lock(); + if (!netif_running(pdata->netdev) || + !test_and_clear_bit(FXGMAC_FLAG_TASK_ESD_CHECK_PENDING, pdata->expansion.task_flags)) + goto out_unlock; + + fxgmac_update_esd_stats(pdata); + fxgmac_check_esd_work(pdata); + fxgmac_schedule_esd_work(pdata); + +out_unlock: + rtnl_unlock(); +} + +static void fxgmac_cancel_esd_work(struct fxgmac_pdata *pdata) +{ + struct work_struct *work = &pdata->expansion.esd_work.work; + + if (!work->func) { + dev_info(pdata->dev, "work func is NULL.\n"); + return; + } + + cancel_delayed_work_sync(&pdata->expansion.esd_work); +} +#endif + unsigned int fxgmac_get_netdev_ip4addr(struct fxgmac_pdata *pdata) { struct net_device *netdev = pdata->netdev; @@ -127,31 +264,51 @@ inline unsigned int fxgmac_rx_dirty_desc(struct fxgmac_ring *ring) return dirty; } -static int fxgmac_maybe_stop_tx_queue(struct fxgmac_channel *channel, +static netdev_tx_t fxgmac_maybe_stop_tx_queue(struct fxgmac_channel *channel, struct fxgmac_ring *ring, unsigned int count) { struct fxgmac_pdata *pdata = channel->pdata; if (count > fxgmac_tx_avail_desc(ring)) { - netif_info( - pdata, drv, pdata->netdev, - "Tx queue stopped, not enough descriptors available\n"); + if (netif_msg_tx_done(pdata)) { + netif_info( + pdata, drv, pdata->netdev, + "Tx queue stopped, not enough descriptors available\n"); + } + + /* Avoid wrongly optimistic queue wake-up: tx poll thread must + * not miss a ring update when it notices a stopped queue. + */ + smp_wmb(); netif_stop_subqueue(pdata->netdev, channel->queue_index); ring->tx.queue_stopped = 1; - /* If we haven't notified the hardware because of xmit_more - * support, tell it now - */ - if (ring->tx.xmit_more) - pdata->hw_ops.tx_start_xmit(channel, ring); - if (netif_msg_tx_done(pdata)) - DPRINTK("about stop tx q, ret BUSY\n"); - - return NETDEV_TX_BUSY; + /* Sync with tx poll: + * - publish queue status and cur ring index (write barrier) + * - refresh dirty ring index (read barrier). + * May the current thread have a pessimistic view of the ring + * status and forget to wake up queue, a racing tx poll thread + * can't. + */ + smp_mb(); + if (count <= fxgmac_tx_avail_desc(ring)) { + ring->tx.queue_stopped = 0; + netif_start_subqueue(pdata->netdev, channel->queue_index); + fxgmac_tx_start_xmit(channel, ring); + } else { + /* If we haven't notified the hardware because of xmit_more + * support, tell it now + */ + if (ring->tx.xmit_more) + fxgmac_tx_start_xmit(channel, ring); + if (netif_msg_tx_done(pdata)) + DPRINTK("about stop tx q, ret BUSY\n"); + return NETDEV_TX_BUSY; + } } - return 0; + return NETDEV_TX_OK; } static void fxgmac_prep_vlan(struct sk_buff *skb, @@ -379,8 +536,9 @@ static void fxgmac_phy_process(struct fxgmac_pdata *pdata) netif_carrier_on(pdata->netdev); if (netif_running(pdata->netdev)) { netif_tx_wake_all_queues(pdata->netdev); - DPRINTK("%s now is link up, mac_speed=%d.\n", - FXGMAC_DRV_NAME, pdata->phy_speed); + dev_info(pdata->dev, "%s now is link up, mac_speed=%d.\n", + netdev_name(pdata->netdev), + pdata->phy_speed); } } else { netif_carrier_off(pdata->netdev); @@ -389,25 +547,95 @@ static void fxgmac_phy_process(struct fxgmac_pdata *pdata) pdata->phy_duplex = DUPLEX_UNKNOWN; hw_ops->disable_rx(pdata); hw_ops->disable_tx(pdata); - DPRINTK("%s now is link down\n", FXGMAC_DRV_NAME); + dev_info(pdata->dev, "%s now is link down\n", netdev_name(pdata->netdev)); } } } -static int fxgmac_phy_poll(struct napi_struct *napi, int budget) +static int fxgmac_misc_poll(struct napi_struct *napi, int budget) { struct fxgmac_pdata *pdata = - container_of(napi, struct fxgmac_pdata, expansion.napi_phy); + container_of(napi, struct fxgmac_pdata, expansion.napi_misc); struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; fxgmac_phy_process(pdata); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) if (napi_complete_done(napi, 0)) hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); +#else + napi_complete(napi); + hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); +#endif return 0; } -static irqreturn_t fxgmac_phy_isr(int irq, void *data) +static void fxgmac_clear_misc_int_status(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval, i, q_count; + + /* clear phy interrupt status */ + hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); + /* clear other interrupt status of misc interrupt */ + regval = pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_ISR); + if (regval) { + if (regval & (1 << 0)) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_PHYIF_STA); + } + if ((regval & (1 << 1)) || (regval & (1 << 2)) || (regval & (1 << 3))) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_AN_SR); + } + if (regval & (1 << 4)) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_PMT_STA); + } + if (regval & (1 << 5)) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_LPI_STA); + } + if (regval & (1 << 8)) { + if (regval & (1 << 9)) { + hw_ops->rx_mmc_int(pdata); + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MMC_RISR); + } + if (regval & (1 << 10)) { + hw_ops->tx_mmc_int(pdata); + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MMC_TISR); + } + if (regval & (1 << 11)) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MMC_IPCRXINT); + } + } + if ((regval & (1 << 13)) || (regval & (1 << 14))) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_TX_RX_STA); + } + + if (regval & (1 << 15)) { + pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MAC_GPIO_SR); + } + } + + /* MTL_Interrupt_Status, write 1 clear */ + regval = pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MTL_INT_SR); + pdata->hw_ops.set_gmac_register(pdata, pdata->mac_regs + MTL_INT_SR, regval); + + /* MTL_Q(#i)_Interrupt_Control_Status, write 1 clear */ + q_count = max(pdata->hw_feat.tx_q_cnt, pdata->hw_feat.rx_q_cnt); + for (i = 0; i < q_count; i++) { + /* Clear all the interrupts which are set */ + regval = pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MTL_Q_INT_CTL_SR + i * MTL_Q_INC); + pdata->hw_ops.set_gmac_register(pdata, pdata->mac_regs + MTL_Q_INT_CTL_SR + i * MTL_Q_INC, regval); + } + + /* MTL_ECC_Interrupt_Status, write 1 clear */ + regval = pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + MTL_ECC_INT_SR); + pdata->hw_ops.set_gmac_register(pdata, pdata->mac_regs + MTL_ECC_INT_SR, regval); + + /* DMA_ECC_Interrupt_Status, write 1 clear */ + regval = pdata->hw_ops.get_gmac_register(pdata, pdata->mac_regs + DMA_ECC_INT_SR); + pdata->hw_ops.set_gmac_register(pdata, pdata->mac_regs + DMA_ECC_INT_SR, regval); +} + +static irqreturn_t fxgmac_misc_isr(int irq, void *data) { struct fxgmac_pdata *pdata = data; struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; @@ -418,9 +646,10 @@ static irqreturn_t fxgmac_phy_isr(int irq, void *data) return IRQ_HANDLED; hw_ops->disable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); - hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); - if (napi_schedule_prep(&pdata->expansion.napi_phy)) { - __napi_schedule_irqoff(&pdata->expansion.napi_phy); + fxgmac_clear_misc_int_status(pdata); + + if (napi_schedule_prep(&pdata->expansion.napi_misc)) { + __napi_schedule_irqoff(&pdata->expansion.napi_misc); } return IRQ_HANDLED; @@ -432,7 +661,7 @@ static irqreturn_t fxgmac_isr(int irq, void *data) struct fxgmac_pdata *pdata = data; struct fxgmac_channel *channel; struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - unsigned int i, ti, ri; + unsigned int i; u32 val; dma_isr = readreg(pdata->pAdapter, pdata->mac_regs + DMA_ISR); @@ -450,24 +679,6 @@ static irqreturn_t fxgmac_isr(int irq, void *data) channel = pdata->channel_head + i; dma_ch_isr = readl(FXGMAC_DMA_REG(channel, DMA_CH_SR)); - netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\n", - i, dma_ch_isr); - - /* The TI or RI interrupt bits may still be set even if using - * per channel DMA interrupts. Check to be sure those are not - * enabled before using the private data napi structure. - */ - ti = FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TI_POS, - DMA_CH_SR_TI_LEN); - ri = FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RI_POS, - DMA_CH_SR_RI_LEN); - if (!pdata->per_channel_irq && (ti || ri)) { - if (napi_schedule_prep(&pdata->expansion.napi)) { - pdata->stats.napi_poll_isr++; - /* Turn on polling */ - __napi_schedule_irqoff(&pdata->expansion.napi); - } - } if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TPS_POS, DMA_CH_SR_TPS_LEN)) @@ -513,12 +724,13 @@ static irqreturn_t fxgmac_isr(int irq, void *data) } if (pdata->expansion.mgm_intctrl_val & MGMT_INT_CTRL0_INT_STATUS_PHY) { - hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, &val); - if (napi_schedule_prep(&pdata->expansion.napi)) { - pdata->stats.napi_poll_isr++; - /* Turn on polling */ - __napi_schedule_irqoff(&pdata->expansion.napi); - } + fxgmac_clear_misc_int_status(pdata); + } + + if (napi_schedule_prep(&pdata->expansion.napi)) { + pdata->stats.napi_poll_isr++; + /* Turn on polling */ + __napi_schedule_irqoff(&pdata->expansion.napi); } return IRQ_HANDLED; @@ -533,27 +745,27 @@ static irqreturn_t fxgmac_dma_isr(int irq, void *data) int message_id; if (irq == channel->expansion.dma_irq_tx) { - message_id = MSI_ID_TXQ0; - hw_ops->disable_msix_one_interrupt(pdata, message_id); - regval = 0; - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_TI_POS, - DMA_CH_SR_TI_LEN, 1); - writereg(pdata->pAdapter, regval, - FXGMAC_DMA_REG(channel, DMA_CH_SR)); if (napi_schedule_prep(&channel->expansion.napi_tx)) { + message_id = MSI_ID_TXQ0; + hw_ops->disable_msix_one_interrupt(pdata, message_id); + regval = 0; + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_TI_POS, + DMA_CH_SR_TI_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); __napi_schedule_irqoff(&channel->expansion.napi_tx); } } else { - message_id = channel->queue_index; - hw_ops->disable_msix_one_interrupt(pdata, message_id); - regval = 0; - regval = readreg(pdata->pAdapter, - FXGMAC_DMA_REG(channel, DMA_CH_SR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_RI_POS, - DMA_CH_SR_RI_LEN, 1); - writereg(pdata->pAdapter, regval, - FXGMAC_DMA_REG(channel, DMA_CH_SR)); if (napi_schedule_prep(&channel->expansion.napi_rx)) { + message_id = channel->queue_index; + hw_ops->disable_msix_one_interrupt(pdata, message_id); + regval = 0; + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_RI_POS, + DMA_CH_SR_RI_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); __napi_schedule_irqoff(&channel->expansion.napi_rx); } } @@ -636,11 +848,23 @@ static void fxgmac_napi_enable(struct fxgmac_pdata *pdata, unsigned int add) { struct fxgmac_channel *channel; unsigned int i; + u32 tx_napi = 0, rx_napi = 0, misc_napi = 0; + + misc_napi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_NAPI_FREE_POS, + FXGMAC_FLAG_MISC_NAPI_FREE_LEN); + tx_napi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_NAPI_FREE_POS, + FXGMAC_FLAG_TX_NAPI_FREE_LEN); + rx_napi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_NAPI_FREE_POS, + FXGMAC_FLAG_RX_NAPI_FREE_LEN); if (pdata->per_channel_irq) { channel = pdata->channel_head; for (i = 0; i < pdata->channel_count; i++, channel++) { - if (add) { + if (!FXGMAC_GET_REG_BITS(rx_napi, + i, FXGMAC_FLAG_PER_CHAN_RX_NAPI_FREE_LEN)) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) netif_napi_add_weight( pdata->netdev, @@ -654,8 +878,13 @@ static void fxgmac_napi_enable(struct fxgmac_pdata *pdata, unsigned int add) #endif } napi_enable(&channel->expansion.napi_rx); + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_NAPI_FREE_POS + i, + FXGMAC_FLAG_PER_CHAN_RX_NAPI_FREE_LEN, + FXGMAC_NAPI_ENABLE); - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i) && !tx_napi) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) netif_napi_add_weight( pdata->netdev, @@ -668,21 +897,33 @@ static void fxgmac_napi_enable(struct fxgmac_pdata *pdata, unsigned int add) NAPI_POLL_WEIGHT); #endif napi_enable(&channel->expansion.napi_tx); + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_NAPI_FREE_POS, + FXGMAC_FLAG_TX_NAPI_FREE_LEN, + FXGMAC_NAPI_ENABLE); } if (netif_msg_drv(pdata)) DPRINTK("napi_enable, msix ch%d napi enabled done, add=%d\n", i, add); } - /* for phy */ + /* for misc */ + if (!misc_napi) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) - netif_napi_add_weight(pdata->netdev, &pdata->expansion.napi_phy, - fxgmac_phy_poll, NAPI_POLL_WEIGHT); + netif_napi_add_weight(pdata->netdev, &pdata->expansion.napi_misc, + fxgmac_misc_poll, NAPI_POLL_WEIGHT); #else - netif_napi_add(pdata->netdev, &pdata->expansion.napi_phy, - fxgmac_phy_poll, NAPI_POLL_WEIGHT); + netif_napi_add(pdata->netdev, &pdata->expansion.napi_misc, + fxgmac_misc_poll, NAPI_POLL_WEIGHT); #endif - napi_enable(&pdata->expansion.napi_phy); + napi_enable(&pdata->expansion.napi_misc); + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_NAPI_FREE_POS, + FXGMAC_FLAG_MISC_NAPI_FREE_LEN, + FXGMAC_NAPI_ENABLE); + } } else { i = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, @@ -706,7 +947,7 @@ static void fxgmac_napi_enable(struct fxgmac_pdata *pdata, unsigned int add) pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( pdata->expansion.int_flags, FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, - FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, 1); + FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, FXGMAC_NAPI_ENABLE); } } } @@ -715,31 +956,59 @@ static void fxgmac_napi_disable(struct fxgmac_pdata *pdata, unsigned int del) { struct fxgmac_channel *channel; unsigned int i; + u32 tx_napi = 0, rx_napi = 0, misc_napi = 0; if (pdata->per_channel_irq) { + misc_napi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_NAPI_FREE_POS, + FXGMAC_FLAG_MISC_NAPI_FREE_LEN); + tx_napi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_NAPI_FREE_POS, + FXGMAC_FLAG_TX_NAPI_FREE_LEN); + rx_napi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_NAPI_FREE_POS, + FXGMAC_FLAG_RX_NAPI_FREE_LEN); channel = pdata->channel_head; if (channel != NULL) { for (i = 0; i < pdata->channel_count; i++, channel++) { - napi_disable(&channel->expansion.napi_rx); + if (FXGMAC_GET_REG_BITS(rx_napi, + i, FXGMAC_FLAG_PER_CHAN_RX_NAPI_FREE_LEN)) { + napi_disable(&channel->expansion.napi_rx); if (del) { netif_napi_del( &channel->expansion.napi_rx); } + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_NAPI_FREE_POS + i, + FXGMAC_FLAG_PER_CHAN_RX_NAPI_FREE_LEN, + FXGMAC_NAPI_DISABLE); + } - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i) && tx_napi) { napi_disable( &channel->expansion.napi_tx); netif_napi_del( &channel->expansion.napi_tx); - } - if (netif_msg_drv(pdata)) - DPRINTK("napi_disable, msix ch%d napi disabled done, del=%d\n", - i, del); + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_NAPI_FREE_POS, + FXGMAC_FLAG_TX_NAPI_FREE_LEN, + FXGMAC_NAPI_DISABLE); + } + if (netif_msg_drv(pdata)) + DPRINTK("napi_disable, msix ch%d napi disabled done, del=%d\n", + i, del); } - napi_disable(&pdata->expansion.napi_phy); - netif_napi_del(&pdata->expansion.napi_phy); + napi_disable(&pdata->expansion.napi_misc); + netif_napi_del(&pdata->expansion.napi_misc); + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_NAPI_FREE_POS, + FXGMAC_FLAG_MISC_NAPI_FREE_LEN, + FXGMAC_NAPI_DISABLE); } } else { i = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, @@ -753,7 +1022,7 @@ static void fxgmac_napi_disable(struct fxgmac_pdata *pdata, unsigned int del) pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( pdata->expansion.int_flags, FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, - FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, 0); + FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, FXGMAC_NAPI_DISABLE); } } } @@ -765,6 +1034,7 @@ static int fxgmac_request_irqs(struct fxgmac_pdata *pdata) unsigned int i; int ret; u32 msi, msix, need_free; + u32 misc = 0, tx = 0, rx = 0; msi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, FXGMAC_FLAG_MSI_POS, FXGMAC_FLAG_MSI_LEN); @@ -793,20 +1063,19 @@ static int fxgmac_request_irqs(struct fxgmac_pdata *pdata) pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( pdata->expansion.int_flags, FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, 1); + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, FXGMAC_IRQ_ENABLE); } } if (!pdata->per_channel_irq) return 0; - ret = devm_request_irq(pdata->dev, pdata->expansion.phy_irq, - fxgmac_phy_isr, 0, netdev->name, pdata); - if (ret) { - netdev_alert(netdev, "error requesting phy irq %d, ret = %d\n", - pdata->expansion.phy_irq, ret); - return ret; - } + tx = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_IRQ_FREE_POS, + FXGMAC_FLAG_TX_IRQ_FREE_LEN); + rx = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_IRQ_FREE_POS, + FXGMAC_FLAG_RX_IRQ_FREE_LEN); channel = pdata->channel_head; for (i = 0; i < pdata->channel_count; i++, channel++) { @@ -814,7 +1083,7 @@ static int fxgmac_request_irqs(struct fxgmac_pdata *pdata) sizeof(channel->expansion.dma_irq_name) - 1, "%s-ch%d-Rx-%u", netdev_name(netdev), i, channel->queue_index); - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i) && !tx) { snprintf(channel->expansion.dma_irq_name_tx, sizeof(channel->expansion.dma_irq_name_tx) - 1, "%s-ch%d-Tx-%u", netdev_name(netdev), i, @@ -826,52 +1095,102 @@ static int fxgmac_request_irqs(struct fxgmac_pdata *pdata) channel->expansion.dma_irq_name_tx, channel); if (ret) { - DPRINTK("fxgmac_req_irqs, err with MSIx irq request for ch %d tx, ret=%d\n", - i, ret); - /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ - devm_free_irq(pdata->dev, - channel->expansion.dma_irq_tx, - channel); - return ret; + netdev_alert(netdev, "fxgmac_req_irqs, err with MSIx irq \ + request for ch %d tx, ret=%d\n", i, ret); + goto err_irq; } + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_IRQ_FREE_POS, + FXGMAC_FLAG_TX_IRQ_FREE_LEN, + FXGMAC_IRQ_ENABLE); + if (netif_msg_drv(pdata)) DPRINTK("fxgmac_req_irqs, MSIx irq_tx request ok, ch=%d, irq=%d,%s\n", - i, channel->expansion.dma_irq_tx, - channel->expansion.dma_irq_name_tx); + i, channel->expansion.dma_irq_tx, + channel->expansion.dma_irq_name_tx); } - ret = devm_request_irq(pdata->dev, channel->dma_irq, - fxgmac_dma_isr, 0, - channel->expansion.dma_irq_name, - channel); + + if (!FXGMAC_GET_REG_BITS(rx, i, FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN)) { + ret = devm_request_irq(pdata->dev, channel->dma_irq, + fxgmac_dma_isr, 0, + channel->expansion.dma_irq_name, + channel); + if (ret) { + netdev_alert(netdev, "error requesting irq %d\n", + channel->dma_irq); + goto err_irq; + } + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_IRQ_FREE_POS + i, + FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN, + FXGMAC_IRQ_ENABLE); + } + } + + misc = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_IRQ_FREE_POS, + FXGMAC_FLAG_MISC_IRQ_FREE_LEN); + if (!misc) { + snprintf(pdata->expansion.misc_irq_name, + sizeof(pdata->expansion.misc_irq_name) - 1, + "%s-misc", netdev_name(netdev)); + ret = devm_request_irq(pdata->dev, + pdata->expansion.misc_irq, + fxgmac_misc_isr, + 0, + pdata->expansion.misc_irq_name, + pdata); if (ret) { - netdev_alert(netdev, "error requesting irq %d\n", - channel->dma_irq); + netdev_alert(netdev, + "error requesting misc irq %d, ret = %d\n", + pdata->expansion.misc_irq, + ret); goto err_irq; } + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_IRQ_FREE_POS, + FXGMAC_FLAG_MISC_IRQ_FREE_LEN, + FXGMAC_IRQ_ENABLE); } - if (netif_msg_drv(pdata)) DPRINTK("fxgmac_req_irqs, MSIx irq request ok, total=%d,%d~%d\n", - i, (pdata->channel_head)[0].dma_irq, - (pdata->channel_head)[i - 1].dma_irq); + i, (pdata->channel_head)[0].dma_irq, (pdata->channel_head)[i-1].dma_irq); return 0; err_irq: - DPRINTK("fxgmac_req_irqs, err with MSIx irq request at %d, ret=%d\n", i, - ret); + netdev_alert(netdev, "fxgmac_req_irqs, err with MSIx irq request at %d, \ + ret=%d\n", i, ret); if (pdata->per_channel_irq) { for (i--, channel--; i < pdata->channel_count; i--, channel--) { - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - devm_free_irq(pdata->dev, - channel->expansion.dma_irq_tx, - channel); + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i) && tx) { + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_IRQ_FREE_POS, + FXGMAC_FLAG_TX_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); + devm_free_irq(pdata->dev, channel->expansion.dma_irq_tx, channel); + } + + if (FXGMAC_GET_REG_BITS(rx, i, FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN)) { + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_IRQ_FREE_POS + i, + FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); + devm_free_irq(pdata->dev, channel->dma_irq, channel); } - devm_free_irq(pdata->dev, channel->dma_irq, channel); } - devm_free_irq(pdata->dev, pdata->expansion.phy_irq, pdata); + if (misc) { + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_IRQ_FREE_POS, + FXGMAC_FLAG_MISC_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); + devm_free_irq(pdata->dev, pdata->expansion.misc_irq, pdata); + } } return ret; } @@ -881,42 +1200,72 @@ static void fxgmac_free_irqs(struct fxgmac_pdata *pdata) struct fxgmac_channel *channel; unsigned int i = 0; u32 need_free, msix; + u32 misc = 0, tx = 0, rx = 0; msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_MSIX_POS, FXGMAC_FLAG_MSIX_LEN); + FXGMAC_FLAG_MSIX_POS, + FXGMAC_FLAG_MSIX_LEN); need_free = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN); + FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN); if (!msix) { if (need_free) { devm_free_irq(pdata->dev, pdata->dev_irq, pdata); - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( - pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, 0); + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); } } if (!pdata->per_channel_irq) return; + misc = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_IRQ_FREE_POS, + FXGMAC_FLAG_MISC_IRQ_FREE_LEN); + tx = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_IRQ_FREE_POS, + FXGMAC_FLAG_TX_IRQ_FREE_LEN); + rx = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_IRQ_FREE_POS, + FXGMAC_FLAG_RX_IRQ_FREE_LEN); + channel = pdata->channel_head; if (channel != NULL) { for (i = 0; i < pdata->channel_count; i++, channel++) { - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - devm_free_irq(pdata->dev, - channel->expansion.dma_irq_tx, - channel); + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i) && tx) { + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_TX_IRQ_FREE_POS, + FXGMAC_FLAG_TX_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); + devm_free_irq(pdata->dev, channel->expansion.dma_irq_tx, channel); if (netif_msg_drv(pdata)) DPRINTK("fxgmac_free_irqs, MSIx irq_tx clear done, ch=%d\n", i); } - devm_free_irq(pdata->dev, channel->dma_irq, channel); + + if (FXGMAC_GET_REG_BITS(rx, i, FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN)) { + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_RX_IRQ_FREE_POS + i, + FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); + devm_free_irq(pdata->dev, channel->dma_irq, channel); + } } - devm_free_irq(pdata->dev, pdata->expansion.phy_irq, pdata); + if (misc) { + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MISC_IRQ_FREE_POS, + FXGMAC_FLAG_MISC_IRQ_FREE_LEN, + FXGMAC_IRQ_DISABLE); + devm_free_irq(pdata->dev, pdata->expansion.misc_irq, pdata); + } } if (netif_msg_drv(pdata)) DPRINTK("fxgmac_free_irqs, MSIx rx irq clear done, total=%d\n", @@ -976,7 +1325,7 @@ void fxgmac_free_rx_data(struct fxgmac_pdata *pdata) static int fxgmac_disable_pci_msi_config(struct pci_dev *pdev) { u16 pcie_cap_offset; - u32 pcie_msi_mask_bits; + u32 pcie_msi_mask_bits = 0; int ret = 0; pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_MSI); @@ -984,7 +1333,7 @@ static int fxgmac_disable_pci_msi_config(struct pci_dev *pdev) ret = pci_read_config_dword(pdev, pcie_cap_offset, &pcie_msi_mask_bits); if (ret) { - printk(KERN_ERR + DPRINTK(KERN_ERR "read pci config space MSI cap. failed, %d\n", ret); ret = -EFAULT; @@ -996,7 +1345,7 @@ static int fxgmac_disable_pci_msi_config(struct pci_dev *pdev) PCI_CAP_ID_MSI_ENABLE_LEN, 0); ret = pci_write_config_dword(pdev, pcie_cap_offset, pcie_msi_mask_bits); if (ret) { - printk(KERN_ERR "write pci config space MSI mask failed, %d\n", + DPRINTK(KERN_ERR "write pci config space MSI mask failed, %d\n", ret); ret = -EFAULT; } @@ -1007,7 +1356,7 @@ static int fxgmac_disable_pci_msi_config(struct pci_dev *pdev) static int fxgmac_disable_pci_msix_config(struct pci_dev *pdev) { u16 pcie_cap_offset; - u32 pcie_msi_mask_bits; + u32 pcie_msi_mask_bits = 0; int ret = 0; pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_MSIX); @@ -1015,7 +1364,7 @@ static int fxgmac_disable_pci_msix_config(struct pci_dev *pdev) ret = pci_read_config_dword(pdev, pcie_cap_offset, &pcie_msi_mask_bits); if (ret) { - printk(KERN_ERR + DPRINTK(KERN_ERR "read pci config space MSIX cap. failed, %d\n", ret); ret = -EFAULT; @@ -1027,7 +1376,7 @@ static int fxgmac_disable_pci_msix_config(struct pci_dev *pdev) PCI_CAP_ID_MSIX_ENABLE_LEN, 0); ret = pci_write_config_dword(pdev, pcie_cap_offset, pcie_msi_mask_bits); if (ret) { - printk(KERN_ERR "write pci config space MSIX mask failed, %d\n", + DPRINTK(KERN_ERR "write pci config space MSIX mask failed, %d\n", ret); ret = -EFAULT; } @@ -1039,21 +1388,27 @@ int fxgmac_start(struct fxgmac_pdata *pdata) { struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; struct net_device *netdev = pdata->netdev; - int ret; unsigned int pcie_low_power = 0; u32 regval; + int ret; if (netif_msg_drv(pdata)) DPRINTK("fxgmac start callin here.\n"); - /* must reset software again here, to avoid flushing tx queue error caused by the system only run probe - * when installing driver on the arm platform. - */ + if (pdata->expansion.dev_state != FXGMAC_DEV_OPEN && + pdata->expansion.dev_state != FXGMAC_DEV_STOP && + pdata->expansion.dev_state != FXGMAC_DEV_RESUME) + return 0; + + /* must reset software again here, to avoid flushing tx queue error + * caused by the system only run probe + * when installing driver on the arm platform. + */ hw_ops->exit(pdata); if (FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_POS, - FXGMAC_FLAG_LEGACY_LEN)) { + FXGMAC_FLAG_LEGACY_POS, + FXGMAC_FLAG_LEGACY_LEN)) { /* * we should disable msi and msix here when we use legacy interrupt, for two reasons: * 1. Exit will restore msi and msix config regisiter, that may enable them. @@ -1075,13 +1430,21 @@ int fxgmac_start(struct fxgmac_pdata *pdata) pcie_low_power & PCIE_LP_ASPM_L1SS, pcie_low_power & PCIE_LP_ASPM_L1, pcie_low_power & PCIE_LP_ASPM_L0S); + if (test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { + netdev_err(pdata->netdev, "fxgmac powerstate is %lu when config power to up.\n", pdata->expansion.powerstate); + } hw_ops->config_power_up(pdata); - fxgmac_dismiss_all_int(pdata); + hw_ops->dismiss_all_int(pdata); + + //control module int to PCIe slot + if (netdev->base_addr) { + regval = (unsigned int)(*((u32 *)(netdev->base_addr + MGMT_INT_CTRL0))); + } ret = hw_ops->init(pdata); if (ret) { - printk("fxgmac hw init error.\n"); + DPRINTK("fxgmac hw init error.\n"); return ret; } fxgmac_napi_enable(pdata, 1); @@ -1110,15 +1473,18 @@ int fxgmac_start(struct fxgmac_pdata *pdata) hw_ops->enable_msix_rxtxphyinterrupt(pdata); fxgmac_enable_rx_tx_ints(pdata); +#ifdef FXGMAC_ESD_CHECK_ENABLED + fxgmac_schedule_esd_work(pdata); +#endif hw_ops->led_under_active(pdata); - + pdata->expansion.dev_state = FXGMAC_DEV_START; return 0; err_napi: fxgmac_napi_disable(pdata, 1); hw_ops->exit(pdata); - DPRINTK("fxgmac start callout with irq err.\n"); + dev_err(pdata->dev, "fxgmac start callout with irq err.\n"); return ret; } @@ -1130,6 +1496,11 @@ void fxgmac_stop(struct fxgmac_pdata *pdata) struct netdev_queue *txq; unsigned int i; + if (pdata->expansion.dev_state != FXGMAC_DEV_START) + return; + + pdata->expansion.dev_state = FXGMAC_DEV_STOP; + if (pdata->per_channel_irq) { hw_ops->disable_msix_interrupt(pdata); } else { @@ -1156,40 +1527,31 @@ void fxgmac_stop(struct fxgmac_pdata *pdata) netdev_tx_reset_queue(txq); } } - - switch (pdata->expansion.current_state) { - case CURRENT_STATE_SUSPEND: - hw_ops->led_under_sleep(pdata); - break; - case CURRENT_STATE_SHUTDOWN: - case CURRENT_STATE_RESTART: - hw_ops->led_under_shutdown(pdata); - break; - case CURRENT_STATE_CLOSE: - break; - default: - break; - } } void fxgmac_restart_dev(struct fxgmac_pdata *pdata) { + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; int ret; /* If not running, "restart" will happen on open */ - if (!netif_running(pdata->netdev)) + if (!netif_running(pdata->netdev) && + pdata->expansion.dev_state != FXGMAC_DEV_START) return; - pdata->expansion.current_state = CURRENT_STATE_RESTART; + fxgmac_lock(pdata); fxgmac_stop(pdata); + hw_ops->led_under_shutdown(pdata); fxgmac_free_tx_data(pdata); fxgmac_free_rx_data(pdata); ret = fxgmac_start(pdata); if (ret) { - printk("fxgmac_restart_dev: fxgmac_start failed.\n"); + DPRINTK("fxgmac_restart_dev: fxgmac_start failed.\n"); } + + fxgmac_unlock(pdata); } static void fxgmac_restart(struct work_struct *work) @@ -1221,7 +1583,7 @@ void fxgmac_net_powerup(struct fxgmac_pdata *pdata) ret = fxgmac_start(pdata); if (ret) { - printk("fxgmac_net_powerup: fxgmac_start error\n"); + DPRINTK("fxgmac_net_powerup: fxgmac_start error\n"); return; } @@ -1266,11 +1628,20 @@ void fxgmac_net_powerdown(struct fxgmac_pdata *pdata, unsigned int wol) /* synchronize_rcu() needed for pending XDP buffers to drain */ synchronize_rcu(); - fxgmac_stop(pdata); /* some works are redundent in this call */ +#ifdef FXGMAC_ESD_CHECK_ENABLED + fxgmac_cancel_esd_work(pdata); +#endif + + fxgmac_stop(pdata); //some works are redundent in this call /* must call it after software reset */ hw_ops->pre_power_down(pdata, false); + if (!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { + netdev_err(pdata->netdev, + "fxgmac powerstate is %lu when config power to down.\n", pdata->expansion.powerstate); + } + /* set mac to lowpower mode and enable wol accordingly */ hw_ops->config_power_down(pdata, wol); @@ -1294,23 +1665,27 @@ static int fxgmac_open(struct net_device *netdev) if (netif_msg_drv(pdata)) DPRINTK("fxgmac_open callin\n"); + fxgmac_lock(pdata); + pdata->expansion.dev_state = FXGMAC_DEV_OPEN; desc_ops = &pdata->desc_ops; - /* TODO: Initialize the phy */ - /* Calculate the Rx buffer size before allocating rings */ ret = fxgmac_calc_rx_buf_size(netdev, netdev->mtu); if (ret < 0) - return ret; + goto unlock; pdata->rx_buf_size = ret; /* Allocate the channels and rings */ - ret = desc_ops->alloc_channles_and_rings(pdata); + ret = desc_ops->alloc_channels_and_rings(pdata); if (ret) - return ret; + goto unlock; INIT_WORK(&pdata->expansion.restart_work, fxgmac_restart); +#ifdef FXGMAC_ESD_CHECK_ENABLED + INIT_DELAYED_WORK(&pdata->expansion.esd_work, fxgmac_esd_work); +#endif + ret = fxgmac_start(pdata); if (ret) goto err_channels_and_rings; @@ -1318,31 +1693,35 @@ static int fxgmac_open(struct net_device *netdev) if (netif_msg_drv(pdata)) DPRINTK("fxgmac_open callout\n"); + fxgmac_unlock(pdata); + return 0; err_channels_and_rings: desc_ops->free_channels_and_rings(pdata); DPRINTK("fxgmac_open callout with channel alloc err\n"); +unlock: + fxgmac_unlock(pdata); return ret; } static int fxgmac_close(struct net_device *netdev) { struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_desc_ops *desc_ops; + struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; if (netif_msg_drv(pdata)) DPRINTK("fxgmac_close callin\n"); - desc_ops = &pdata->desc_ops; - - pdata->expansion.current_state = - (pdata->expansion.current_state == CURRENT_STATE_SHUTDOWN) ? - pdata->expansion.current_state : - CURRENT_STATE_CLOSE; + fxgmac_lock(pdata); /* Stop the device */ fxgmac_stop(pdata); + pdata->expansion.dev_state = FXGMAC_DEV_CLOSE; + +#ifdef FXGMAC_ESD_CHECK_ENABLED + fxgmac_cancel_esd_work(pdata); +#endif /* Free the channels and rings */ desc_ops->free_channels_and_rings(pdata); @@ -1352,6 +1731,7 @@ static int fxgmac_close(struct net_device *netdev) if (netif_msg_drv(pdata)) DPRINTK("fxgmac_close callout\n"); + fxgmac_unlock(pdata); return 0; } @@ -1373,7 +1753,7 @@ static void fxgmac_tx_timeout(struct net_device *netdev, unsigned int unused) #endif } -static int fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) +static netdev_tx_t fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) { struct fxgmac_pdata *pdata = netdev_priv(netdev); struct fxgmac_pkt_info *tx_pkt_info; @@ -1418,7 +1798,6 @@ static int fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) if (ret) { netif_err(pdata, tx_err, netdev, "error processing TSO packet\n"); - DPRINTK("dev_xmit, tx err for TSO\n"); dev_kfree_skb_any(skb); return ret; } @@ -1426,7 +1805,7 @@ static int fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) if (!desc_ops->map_tx_skb(channel, skb)) { dev_kfree_skb_any(skb); - DPRINTK("xmit, map tx skb err\n"); + netif_err(pdata, tx_err, netdev, "xmit, map tx skb err\n"); return NETDEV_TX_OK; } @@ -1437,10 +1816,8 @@ static int fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) tx_pkt_info->tx_bytes); /* Configure required descriptor fields for transmission */ - hw_ops->dev_xmit(channel); -#if FXGMAC_DUMMY_TX_DEBUG - DPRINTK("tx hw_ops->dev_xmit ok\n"); -#endif + fxgmac_dev_xmit(channel); + if (netif_msg_pktdata(pdata)) fxgmac_dbg_pkt(netdev, skb, true); @@ -1512,7 +1889,12 @@ static int fxgmac_set_mac_address(struct net_device *netdev, void *addr) return 0; } -/* cmd = [0x89F0, 0x89FF] */ +/* + * cmd = [0x89F0, 0x89FF] + * When using it, we must pay attention to the thread synchronization + * of this interface. Because it's an external call that isn't + * initiated by the OS. + */ static int fxgmac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct file f; @@ -1554,6 +1936,12 @@ static int fxgmac_change_mtu(struct net_device *netdev, int mtu) int old_mtu = netdev->mtu; #endif + if (mtu > FXGMAC_JUMBO_PACKET_MTU) { + netdev_alert(netdev, "MTU exceeds maximum supported value\n"); + return -EINVAL; + } + + fxgmac_lock(pdata); fxgmac_stop(pdata); fxgmac_free_tx_data(pdata); @@ -1580,6 +1968,8 @@ static int fxgmac_change_mtu(struct net_device *netdev, int mtu) DPRINTK("fxgmac, set MTU from %d to %d.\n", old_mtu, netdev->mtu); #endif + fxgmac_unlock(pdata); + return 0; } @@ -1653,11 +2043,11 @@ static int fxgmac_set_features(struct net_device *netdev, tso = pdata->expansion.netdev_features & (NETIF_F_TSO | NETIF_F_TSO6); if ((features & (NETIF_F_TSO | NETIF_F_TSO6)) && !tso) { - printk("enable tso.\n"); + DPRINTK("enable tso.\n"); pdata->hw_feat.tso = 1; hw_ops->config_tso(pdata); } else if (!(features & (NETIF_F_TSO | NETIF_F_TSO6)) && tso) { - printk("disable tso.\n"); + DPRINTK("disable tso.\n"); pdata->hw_feat.tso = 0; hw_ops->config_tso(pdata); } @@ -1730,11 +2120,11 @@ static void fxgmac_rx_refresh(struct fxgmac_channel *channel) struct fxgmac_pdata *pdata = channel->pdata; struct fxgmac_ring *ring = channel->rx_ring; struct fxgmac_desc_data *desc_data; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; while (ring->dirty != ring->cur) { desc_data = FXGMAC_GET_DESC_DATA(ring, ring->dirty); - hw_ops->rx_desc_reset(pdata, desc_data, ring->dirty); + desc_ops->rx_desc_reset(pdata, desc_data, ring->dirty); ring->dirty = FXGMAC_GET_ENTRY(ring->dirty, ring->dma_desc_count); } @@ -1938,7 +2328,7 @@ static int fxgmac_tx_poll(struct fxgmac_channel *channel) /* Free the SKB and reset the descriptor for re-use */ desc_ops->unmap_desc_data(pdata, desc_data); - hw_ops->tx_desc_reset(desc_data); + desc_ops->tx_desc_reset(desc_data); processed++; ring->dirty = @@ -1950,6 +2340,7 @@ static int fxgmac_tx_poll(struct fxgmac_channel *channel) netdev_tx_completed_queue(txq, tx_packets, tx_bytes); + smp_wmb(); if ((ring->tx.queue_stopped == 1) && (fxgmac_tx_avail_desc(ring) > FXGMAC_TX_DESC_MIN_FREE)) { ring->tx.queue_stopped = 0; @@ -2005,7 +2396,7 @@ static int fxgmac_rx_poll(struct fxgmac_channel *channel, int budget) if (fxgmac_rx_dirty_desc(ring) > FXGMAC_RX_DESC_MAX_DIRTY) fxgmac_rx_refresh(channel); - if (hw_ops->dev_read(channel)) + if (fxgmac_dev_read(channel)) break; ring->cur = FXGMAC_GET_ENTRY(ring->cur, ring->dma_desc_count); @@ -2029,6 +2420,7 @@ static int fxgmac_rx_poll(struct fxgmac_channel *channel, int budget) netif_err(pdata, rx_err, netdev, "error in received packet\n"); dev_kfree_skb(skb); + pdata->netdev->stats.rx_dropped++; goto next_packet; } @@ -2036,20 +2428,20 @@ static int fxgmac_rx_poll(struct fxgmac_channel *channel, int budget) len = desc_data->rx.len; if (len > pdata->rx_buf_size) { if (net_ratelimit()) - netdev_err( - pdata->netdev, + netif_err(pdata, rx_err, netdev, "len %d larger than size (%d)\n", len, pdata->rx_buf_size); + pdata->netdev->stats.rx_length_errors++; pdata->netdev->stats.rx_dropped++; goto next_packet; } if (len == 0) { if (net_ratelimit()) - netdev_err( - pdata->netdev, + netif_err(pdata, rx_err, netdev, "A packet of length 0 was received\n"); pdata->netdev->stats.rx_length_errors++; + pdata->netdev->stats.rx_dropped++; goto next_packet; } @@ -2058,16 +2450,17 @@ static int fxgmac_rx_poll(struct fxgmac_channel *channel, int budget) len); if (unlikely(!skb)) { if (net_ratelimit()) - netdev_warn( - pdata->netdev, - "create skb failed\n"); + netif_err(pdata, rx_err, netdev, "create skb failed\n"); + pdata->netdev->stats.rx_dropped++; goto next_packet; } } } - if (!skb) + if (!skb) { + pdata->netdev->stats.rx_dropped++; goto next_packet; + } if (netif_msg_pktdata(pdata)) fxgmac_print_pkt(netdev, skb, false); @@ -2264,9 +2657,9 @@ static int fxgmac_one_poll_rx(struct napi_struct *napi, int budget) processed = fxgmac_rx_poll(channel, budget); if (processed < budget) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) - /* if there no interrupt occured when this interrupt running, struct napi's state is NAPIF_STATE_SCHED, + /* if there no interrupt occurred when this interrupt running, struct napi's state is NAPIF_STATE_SCHED, * napi_complete_done return true and we can enable irq, it will not cause unbalanced iqr issure. - * if there more interrupt occured when this interrupt running, struct napi's state is NAPIF_STATE_SCHED | NAPIF_STATE_MISSED + * if there more interrupt occurred when this interrupt running, struct napi's state is NAPIF_STATE_SCHED | NAPIF_STATE_MISSED * because napi_schedule_prep will make it. At this time napi_complete_done will return false and * schedule poll again because of NAPIF_STATE_MISSED, it will cause unbalanced irq issure. */ @@ -2317,8 +2710,13 @@ static int fxgmac_all_poll(struct napi_struct *napi, int budget) /* If we processed everything, we are done */ if (processed < budget) { /* Turn off polling */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) if (napi_complete_done(napi, processed)) hw_ops->enable_mgm_interrupt(pdata); +#else + napi_complete(napi); + hw_ops->enable_mgm_interrupt(pdata); +#endif } if ((processed) && (netif_msg_rx_status(pdata))) { @@ -2327,3 +2725,468 @@ static int fxgmac_all_poll(struct napi_struct *napi, int budget) return processed; } + +void fxgmac_tx_start_xmit(struct fxgmac_channel *channel, + struct fxgmac_ring *ring) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_desc_data *desc_data; + + /* Make sure everything is written before the register write */ + wmb(); + + /* Issue a poll command to Tx DMA by writing address + * of next immediate free descriptor + */ + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); + + writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)); + + if (netif_msg_tx_done(pdata)) { + DPRINTK("tx_start_xmit: dump before wr reg, \ + dma base=0x%016llx,reg=0x%08x, \ + tx timer usecs=%u,tx_timer_active=%u\n", + desc_data->dma_desc_addr, + readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)), + pdata->tx_usecs, channel->tx_timer_active); + } + + ring->tx.xmit_more = 0; +} + +void fxgmac_dev_xmit(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->tx_ring; + unsigned int tso_context, vlan_context; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_pkt_info *pkt_info; + unsigned int csum, tso, vlan; + int start_index = ring->cur; + int cur_index = ring->cur; + int i; + + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit callin, desc cur=%d\n", cur_index); + + pkt_info = &ring->pkt_info; + csum = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN); + tso = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN); + vlan = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN); + + if (tso && (pkt_info->mss != ring->tx.cur_mss)) + tso_context = 1; + else + tso_context = 0; + + if ((tso_context) && (netif_msg_tx_done(pdata))) { + /* tso is initialized to start... */ + DPRINTK("fxgmac_dev_xmit, tso_%s tso=0x%x, pkt_mss=%d, cur_mss=%d\n", + (pkt_info->mss) ? "start" : "stop", tso, pkt_info->mss, + ring->tx.cur_mss); + } + + if (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag)) + vlan_context = 1; + else + vlan_context = 0; + + if (vlan && (netif_msg_tx_done(pdata))) + DPRINTK("fxgmac_dev_xmi:pkt vlan=%d, ring vlan=%d, vlan_context=%d\n", + pkt_info->vlan_ctag, ring->tx.cur_vlan_ctag, + vlan_context); + + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + dma_desc = desc_data->dma_desc; + + /* Create a context descriptor if this is a TSO pkt_info */ + if (tso_context || vlan_context) { + if (tso_context) { + if (netif_msg_tx_done(pdata)) + DPRINTK("xlgamc dev xmit, construct tso context descriptor, mss=%u\n", + pkt_info->mss); + + /* Set the MSS size */ + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_CONTEXT_DESC2_MSS_POS, + TX_CONTEXT_DESC2_MSS_LEN, pkt_info->mss); + + /* Mark it as a CONTEXT descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_CTXT_POS, + TX_CONTEXT_DESC3_CTXT_LEN, 1); + + /* Indicate this descriptor contains the MSS */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_TCMSSV_POS, + TX_CONTEXT_DESC3_TCMSSV_LEN, 1); + + ring->tx.cur_mss = pkt_info->mss; + } + + if (vlan_context) { + netif_dbg(pdata, tx_queued, pdata->netdev, + "VLAN context descriptor, ctag=%u\n", + pkt_info->vlan_ctag); + + /* Mark it as a CONTEXT descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_CTXT_POS, + TX_CONTEXT_DESC3_CTXT_LEN, 1); + + /* Set the VLAN tag */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_VT_POS, + TX_CONTEXT_DESC3_VT_LEN, pkt_info->vlan_ctag); + + /* Indicate this descriptor contains the VLAN tag */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_VLTV_POS, + TX_CONTEXT_DESC3_VLTV_LEN, 1); + + ring->tx.cur_vlan_ctag = pkt_info->vlan_ctag; + } + + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + dma_desc = desc_data->dma_desc; + } + + /* Update buffer address (for TSO this is the header) */ + dma_desc->desc0 = cpu_to_le32(lower_32_bits(desc_data->skb_dma)); + dma_desc->desc1 = cpu_to_le32(upper_32_bits(desc_data->skb_dma)); + + /* Update the buffer length */ + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc2, + TX_NORMAL_DESC2_HL_B1L_POS, + TX_NORMAL_DESC2_HL_B1L_LEN, + desc_data->skb_dma_len); + + /* VLAN tag insertion check */ + if (vlan) { + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_NORMAL_DESC2_VTIR_POS, + TX_NORMAL_DESC2_VTIR_LEN, TX_NORMAL_DESC2_VLAN_INSERT); + pdata->stats.tx_vlan_packets++; + } + + /* Timestamp enablement check */ + if (FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_PTP_POS, + TX_PACKET_ATTRIBUTES_PTP_LEN)) + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_NORMAL_DESC2_TTSE_POS, + TX_NORMAL_DESC2_TTSE_LEN, 1); + + /* Mark it as First Descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_FD_POS, + TX_NORMAL_DESC3_FD_LEN, 1); + + /* Mark it as a NORMAL descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_CTXT_POS, + TX_NORMAL_DESC3_CTXT_LEN, 0); + + /* Set OWN bit if not the first descriptor */ + if (cur_index != start_index) + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN, 1); + + if (tso) { + /* Enable TSO */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_TSE_POS, + TX_NORMAL_DESC3_TSE_LEN, 1); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_TCPPL_POS, + TX_NORMAL_DESC3_TCPPL_LEN, pkt_info->tcp_payload_len); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_TCPHDRLEN_POS, + TX_NORMAL_DESC3_TCPHDRLEN_LEN, + pkt_info->tcp_header_len / 4); + + pdata->stats.tx_tso_packets++; + } else { + /* Enable CRC and Pad Insertion */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CPC_POS, + TX_NORMAL_DESC3_CPC_LEN, 0); + + /* Enable HW CSUM */ + if (csum) + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CIC_POS, + TX_NORMAL_DESC3_CIC_LEN, 0x3); + + /* Set the total length to be transmitted */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_FL_POS, + TX_NORMAL_DESC3_FL_LEN, + pkt_info->length); + } + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit before more descs, desc cur=%d, start=%d, desc=%#x,%#x,%#x,%#x\n", + cur_index, start_index, dma_desc->desc0, + dma_desc->desc1, dma_desc->desc2, dma_desc->desc3); + + if (start_index <= cur_index) + i = cur_index - start_index + 1; + else + i = ring->dma_desc_count - start_index + cur_index; + + for (; i < pkt_info->desc_count; i++) { + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + dma_desc = desc_data->dma_desc; + + /* Update buffer address */ + dma_desc->desc0 = + cpu_to_le32(lower_32_bits(desc_data->skb_dma)); + dma_desc->desc1 = + cpu_to_le32(upper_32_bits(desc_data->skb_dma)); + + /* Update the buffer length */ + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_NORMAL_DESC2_HL_B1L_POS, + TX_NORMAL_DESC2_HL_B1L_LEN, desc_data->skb_dma_len); + + /* Set OWN bit */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN, 1); + + /* Mark it as NORMAL descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CTXT_POS, + TX_NORMAL_DESC3_CTXT_LEN, 0); + + /* Enable HW CSUM */ + if (csum) + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CIC_POS, + TX_NORMAL_DESC3_CIC_LEN, 0x3); + } + + /* Set LAST bit for the last descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_LD_POS, + TX_NORMAL_DESC3_LD_LEN, 1); + + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc2, + TX_NORMAL_DESC2_IC_POS, + TX_NORMAL_DESC2_IC_LEN, 1); + + /* Save the Tx info to report back during cleanup */ + desc_data->tx.packets = pkt_info->tx_packets; + desc_data->tx.bytes = pkt_info->tx_bytes; + + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit last descs, desc cur=%d, desc=%#x,%#x,%#x,%#x\n", + cur_index, dma_desc->desc0, dma_desc->desc1, + dma_desc->desc2, dma_desc->desc3); + + /* In case the Tx DMA engine is running, make sure everything + * is written to the descriptor(s) before setting the OWN bit + * for the first descriptor + */ + dma_wmb(); + + /* Set OWN bit for the first descriptor */ + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + dma_desc = desc_data->dma_desc; + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN, 1); + + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit first descs, start=%d, desc=%#x,%#x,%#x,%#x\n", + start_index, dma_desc->desc0, dma_desc->desc1, + dma_desc->desc2, dma_desc->desc3); + + if (netif_msg_tx_queued(pdata)) + fxgmac_dump_tx_desc(pdata, ring, start_index, + pkt_info->desc_count, 1); + + /* Make sure ownership is written to the descriptor */ + smp_wmb(); + + ring->cur = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + + fxgmac_tx_start_xmit(channel, ring); + + /* yzhang for reduce debug output */ + if (netif_msg_tx_done(pdata)) { + DPRINTK("dev_xmit callout %s: descriptors %u to %u written\n", + channel->name, start_index & (ring->dma_desc_count - 1), + (ring->cur - 1) & (ring->dma_desc_count - 1)); + } +} + +extern void fxgmac_diag_get_rx_info(struct fxgmac_channel *channel); + +static void fxgmac_get_rx_tstamp(struct fxgmac_pkt_info *pkt_info, + struct fxgmac_dma_desc *dma_desc) +{ + u64 nsec; + + nsec = le32_to_cpu(dma_desc->desc1); + nsec <<= 32; + nsec |= le32_to_cpu(dma_desc->desc0); + if (nsec != 0xffffffffffffffffULL) { + pkt_info->rx_tstamp = nsec; + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS, + RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN, 1); + } +} + +int fxgmac_dev_read(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->rx_ring; + struct net_device *netdev = pdata->netdev; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_pkt_info *pkt_info; + unsigned int err, etlt, l34t; + + static unsigned int cnt_incomplete; + + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); + dma_desc = desc_data->dma_desc; + pkt_info = &ring->pkt_info; + + /* Check for data availability */ + if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_OWN_POS, + RX_NORMAL_DESC3_OWN_LEN)) { + return 1; + } + + /* Make sure descriptor fields are read after reading the OWN bit */ + dma_rmb(); + + if (netif_msg_rx_status(pdata)) + fxgmac_dump_rx_desc(pdata, ring, ring->cur); + + if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_CTXT_POS, + RX_NORMAL_DESC3_CTXT_LEN)) { + /* Timestamp Context Descriptor */ + fxgmac_get_rx_tstamp(pkt_info, dma_desc); + + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_LEN, 1); + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN, 0); + if (netif_msg_rx_status(pdata)) + DPRINTK("dev_read context desc, ch=%s\n", channel->name); + return 0; + } + + /* Normal Descriptor, be sure Context Descriptor bit is off */ + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CONTEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_LEN, + 0); + + /* Get the header length */ + if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_FD_POS, + RX_NORMAL_DESC3_FD_LEN)) { + desc_data->rx.hdr_len = FXGMAC_GET_REG_BITS_LE( + dma_desc->desc2, RX_NORMAL_DESC2_HL_POS, + RX_NORMAL_DESC2_HL_LEN); + if (desc_data->rx.hdr_len) + pdata->stats.rx_split_header_packets++; + } + l34t = 0; + + /* Get the pkt_info length */ + desc_data->rx.len = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_PL_POS, + RX_NORMAL_DESC3_PL_LEN); + + if (!FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_LD_POS, + RX_NORMAL_DESC3_LD_LEN)) { + /* Not all the data has been transferred for this pkt_info */ + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, + RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, 1); + cnt_incomplete++; + if ((cnt_incomplete < 2) && netif_msg_rx_status(pdata)) + DPRINTK("dev_read NOT last desc, pkt incomplete yet,%u\n", + cnt_incomplete); + + return 0; + } + if ((cnt_incomplete) && netif_msg_rx_status(pdata)) + DPRINTK("dev_read rx back to normal and incomplete cnt=%u\n", cnt_incomplete); + cnt_incomplete = 0; /* when back to normal, reset cnt */ + + /* This is the last of the data for this pkt_info */ + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, + RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, 0); + + /* Set checksum done indicator as appropriate */ + if (netdev->features & NETIF_F_RXCSUM) + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, + RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 1); + + /* Check for errors (only valid in last descriptor) */ + err = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_ES_POS, + RX_NORMAL_DESC3_ES_LEN); + etlt = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_ETLT_POS, + RX_NORMAL_DESC3_ETLT_LEN); + if ((err) && netif_msg_rx_status(pdata)) { + DPRINTK("dev_read:head_len=%u, pkt_len=%u, err=%u, etlt=%#x, desc2=0x%08x, desc3=0x%08x\n", + desc_data->rx.hdr_len, desc_data->rx.len, err, etlt, + dma_desc->desc2, dma_desc->desc3); + } + + if (!err || !etlt) { + /* No error if err is 0 or etlt is 0 */ + if ((etlt == 0x4 /*yzhang changed to 0x4, 0x09*/) && + (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) { + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN, 1); + pkt_info->vlan_ctag = FXGMAC_GET_REG_BITS_LE( + dma_desc->desc0, RX_NORMAL_DESC0_OVT_POS, + RX_NORMAL_DESC0_OVT_LEN); + netif_dbg(pdata, rx_status, netdev, "vlan-ctag=%#06x\n", + pkt_info->vlan_ctag); + } + } else { + if (etlt == 0x05 || etlt == 0x06) + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, + RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 0); + else + pkt_info->errors = FXGMAC_SET_REG_BITS( + pkt_info->errors, RX_PACKET_ERRORS_FRAME_POS, + RX_PACKET_ERRORS_FRAME_LEN, 1); + } + + return 0; +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c index f6f8f4f6a5e9b..7899f36c17bd9 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c @@ -56,14 +56,15 @@ static int fxgmac_probe(struct pci_dev *pcidev, const struct pci_device_id *id) static void fxgmac_remove(struct pci_dev *pcidev) { - struct net_device *netdev = dev_get_drvdata(&pcidev->dev); - struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct net_device *netdev; + struct fxgmac_pdata *pdata; + u32 msix; -#ifdef CONFIG_PCI_MSI - u32 msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + netdev = dev_get_drvdata(&pcidev->dev); + pdata = netdev_priv(netdev); + msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, FXGMAC_FLAG_MSIX_POS, FXGMAC_FLAG_MSIX_LEN); -#endif fxgmac_drv_remove(&pcidev->dev); #ifdef CONFIG_PCI_MSI @@ -123,14 +124,16 @@ static int __fxgmac_shutdown(struct pci_dev *pdev, bool *enable_wake) static void fxgmac_shutdown(struct pci_dev *pdev) { - bool wake; struct net_device *netdev = dev_get_drvdata(&pdev->dev); struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + bool wake; DPRINTK("fxpm, fxgmac_shutdown callin\n"); - pdata->expansion.current_state = CURRENT_STATE_SHUTDOWN; + fxgmac_lock(pdata); __fxgmac_shutdown(pdev, &wake); + hw_ops->led_under_shutdown(pdata); if (system_state == SYSTEM_POWER_OFF) { pci_wake_from_d3(pdev, wake); @@ -138,6 +141,7 @@ static void fxgmac_shutdown(struct pci_dev *pdev) } DPRINTK("fxpm, fxgmac_shutdown callout, system power off=%d\n", (system_state == SYSTEM_POWER_OFF) ? 1 : 0); + fxgmac_unlock(pdata); } #ifdef CONFIG_PM @@ -145,22 +149,26 @@ static void fxgmac_shutdown(struct pci_dev *pdev) static int fxgmac_suspend(struct pci_dev *pdev, pm_message_t __always_unused state) { - int retval; - bool wake; struct net_device *netdev = dev_get_drvdata(&pdev->dev); struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int retval = 0; + bool wake; DPRINTK("fxpm, fxgmac_suspend callin\n"); - pdata->expansion.current_state = CURRENT_STATE_SUSPEND; + fxgmac_lock(pdata); + if (pdata->expansion.dev_state != FXGMAC_DEV_START) + goto unlock; if (netif_running(netdev)) { retval = __fxgmac_shutdown(pdev, &wake); if (retval) - return retval; + goto unlock; } else { wake = !!(pdata->expansion.wol); } + hw_ops->led_under_sleep(pdata); if (wake) { pci_prepare_to_sleep(pdev); @@ -169,24 +177,28 @@ static int fxgmac_suspend(struct pci_dev *pdev, pci_set_power_state(pdev, PCI_D3hot); } + pdata->expansion.dev_state = FXGMAC_DEV_SUSPEND; DPRINTK("fxpm, fxgmac_suspend callout to %s\n", wake ? "sleep" : "D3hot"); - return 0; +unlock: + fxgmac_unlock(pdata); + return retval; } static int fxgmac_resume(struct pci_dev *pdev) { - struct fxgmac_pdata *pdata; - struct net_device *netdev; + struct net_device *netdev = dev_get_drvdata(&pdev->dev); + struct fxgmac_pdata *pdata = netdev_priv(netdev); u32 err; DPRINTK("fxpm, fxgmac_resume callin\n"); - netdev = dev_get_drvdata(&pdev->dev); - pdata = netdev_priv(netdev); + fxgmac_lock(pdata); + if (pdata->expansion.dev_state != FXGMAC_DEV_SUSPEND) + goto unlock; - pdata->expansion.current_state = CURRENT_STATE_RESUME; + pdata->expansion.dev_state = FXGMAC_DEV_RESUME; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); @@ -198,9 +210,8 @@ static int fxgmac_resume(struct pci_dev *pdev) err = pci_enable_device_mem(pdev); if (err) { - dev_err(pdata->dev, - "fxgmac_resume, failed to enable PCI device from suspend\n"); - return err; + dev_err(pdata->dev, "fxgmac_resume, failed to enable PCI device from suspend\n"); + goto unlock; } smp_mb__before_atomic(); __clear_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate); @@ -219,7 +230,8 @@ static int fxgmac_resume(struct pci_dev *pdev) rtnl_unlock(); DPRINTK("fxpm, fxgmac_resume callout\n"); - +unlock: + fxgmac_unlock(pdata); return err; } #endif diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c index 88066a110f410..50d523caa06c8 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c @@ -7,6 +7,39 @@ #include "fuxi-gmac.h" #include "fuxi-gmac-reg.h" +/* + * When in forced mode, set the speed, duplex, and auto-negotiation of the PHY + * all at once to avoid the problems caused by individual settings + * on some machines + */ +void fxgmac_phy_force_mode(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval = 0; + unsigned int high_bit = 0, low_bit = 0; + + switch (pdata->phy_speed) { + case SPEED_1000: + high_bit = 1, low_bit = 0; + break; + case SPEED_100: + high_bit = 0, low_bit = 1; + break; + case SPEED_10: + high_bit = 0, low_bit = 0; + break; + default: + break; + } + + hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN, pdata->phy_autoeng); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_H_POS, PHY_CR_SPEED_SEL_H_LEN, high_bit); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_L_POS, PHY_CR_SPEED_SEL_L_LEN, low_bit); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_DUPLEX_POS, PHY_CR_DUPLEX_LEN, pdata->phy_duplex); + hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed) { struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; @@ -27,10 +60,7 @@ void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed) break; } - /* disable autoneg */ hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, - PHY_CR_AUTOENG_LEN, 0); regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_H_POS, PHY_CR_SPEED_SEL_H_LEN, high_bit); regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_L_POS, diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h index 65d6288e6869a..e0a6dbe8aa95c 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h @@ -406,7 +406,7 @@ #define MMC_CR_MCF_POS 3 #define MMC_CR_MCF_LEN 1 #define MMC_RIER_ALL_INTERRUPTS_POS 0 -#define MMC_RIER_ALL_INTERRUPTS_LEN 26 +#define MMC_RIER_ALL_INTERRUPTS_LEN 28 #define MMC_RISR_RXFRAMECOUNT_GB_POS 0 #define MMC_RISR_RXFRAMECOUNT_GB_LEN 1 #define MMC_RISR_RXOCTETCOUNT_GB_POS 1 @@ -465,7 +465,7 @@ #define MMC_RISR_RXLPITRANSITION_LEN 1 #define MMC_TIER_ALL_INTERRUPTS_POS 0 -#define MMC_TIER_ALL_INTERRUPTS_LEN 26 +#define MMC_TIER_ALL_INTERRUPTS_LEN 28 #define MMC_TISR_TXOCTETCOUNT_GB_POS 0 #define MMC_TISR_TXOCTETCOUNT_GB_LEN 1 #define MMC_TISR_TXFRAMECOUNT_GB_POS 1 @@ -1037,6 +1037,8 @@ #define PHY_CR_SPEED_SEL_L_LEN 1 #define PHY_CR_AUTOENG_POS 12 #define PHY_CR_AUTOENG_LEN 1 +#define PHY_CR_POWER_POS 11 +#define PHY_CR_POWER_LEN 1 #define PHY_CR_RE_AUTOENG_POS 9 #define PHY_CR_RE_AUTOENG_LEN 1 #define PHY_CR_DUPLEX_POS 8 @@ -1060,6 +1062,10 @@ #define PHY_MII_ADVERTISE_10HALF_POS 5 #define PHY_MII_ADVERTISE_10HALF_LEN 1 #define REG_MII_LPA 0x05 /* Link partner ability reg */ +#define PHY_MII_LINK_PARNTNER_10FULL_POS 6 +#define PHY_MII_LINK_PARNTNER_10FULL_LEN 1 +#define PHY_MII_LINK_PARNTNER_10HALF_POS 5 +#define PHY_MII_LINK_PARNTNER_10HALF_LEN 1 #define REG_MII_EXPANSION 0x06 /* Expansion register */ #define REG_MII_NEXT_PAGE 0x07 /* Next page register */ #define REG_MII_LPR_NEXT_PAGE 0x08 /* LPR next page register */ @@ -1210,9 +1216,10 @@ #define REG_MII_EXT_SLEEP_REG_CLEAN_LOOPBACK 0xe812 #define REG_MII_EXT_ANALOG_CFG2 0x51 -#define REG_MII_EXT_ANALOG_CFG2_LED_VALUE 0x4a9 +#define REG_MII_EXT_ANALOG_CFG2_VALUE 0x4a9 #define REG_MII_EXT_ANALOG_CFG8 0x57 -#define REG_MII_EXT_ANALOG_CFG8_LED_VALUE 0x274c +#define REG_MII_EXT_ANALOG_CFG8_VALUE 0x274c +#define REG_MII_EXT_ANALOG_CFG8_137D1D05_VALUE 0x264c #define REG_MII_EXT_COMMON_LED_CFG 0xA00B #define REG_MII_EXT_COMMON_LED0_CFG 0xA00C @@ -1302,7 +1309,7 @@ #define MGMT_EPHY_CTRL_STA_SPEED_LEN 2 #define MGMT_EPHY_CTRL_STA_SPEED_MASK 0x18 -#define MGMT_EPHY_CTRL_ERROR_VAULE 0xFFFFFFFF +#define MGMT_EPHY_CTRL_ERROR_VALUE 0xFFFFFFFF #define MGMT_PCIE_EP_CTRL 0x1008 @@ -1390,7 +1397,7 @@ Two working mode: 1. SW trigger LTR idle threshold timer set as 0, enable LTR enable will trigger one LTR message -Note: PCIe cfg enable should set in initilization before enable LTR. +Note : PCIe cfg enable should set in initialization before enable LTR. 2. HW auto trigger LTR idle threshold timer set as one non-zero value, HW monitor system status, when system idle timer over threshold, HW send out LTR message @@ -1425,7 +1432,7 @@ system exit idle state, send out one LTR exit message. #define LTR_IDLE_EXIT 0x1140 /* LTR_CTRL4, LTR latency message, only for System IDLE End. */ #define LTR_IDLE_EXIT_POS 0 #define LTR_IDLE_EXIT_LEN 10 -#define LTR_IDLE_EXIT_USVAL 2 +#define LTR_IDLE_EXIT_USVAL 171 #define LTR_IDLE_EXIT_SCALE_POS 10 #define LTR_IDLE_EXIT_SCALE_LEN 5 #define LTR_IDLE_EXIT_SCALE 2 @@ -1891,4 +1898,6 @@ system exit idle state, send out one LTR exit message. #define POWER_EIOS_POS 7 #define POWER_EIOS_LEN 1 +#define TONGFANGID_137D1D05_ADJUST_SI 0x137D1D05 + #endif /* __FUXI_GMAC_REG_H__ */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h index ea01ebdadc4e3..c95caca0433d8 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h @@ -438,7 +438,7 @@ struct fxphy_ag_adv { }; struct fxgmac_desc_ops { - int (*alloc_channles_and_rings)(struct fxgmac_pdata *pdata); + int (*alloc_channels_and_rings)(struct fxgmac_pdata *pdata); void (*free_channels_and_rings)(struct fxgmac_pdata *pdata); int (*map_tx_skb)(struct fxgmac_channel *channel, struct sk_buff *skb); int (*map_rx_buffer)(struct fxgmac_pdata *pdata, @@ -448,6 +448,13 @@ struct fxgmac_desc_ops { struct fxgmac_desc_data *desc_data); void (*tx_desc_init)(struct fxgmac_pdata *pdata); void (*rx_desc_init)(struct fxgmac_pdata *pdata); + /* For descriptor related operation */ + void (*tx_desc_init_channel)(struct fxgmac_channel *channel); + void (*rx_desc_init_channel)(struct fxgmac_channel *channel); + void (*tx_desc_reset)(struct fxgmac_desc_data *desc_data); + void (*rx_desc_reset)(struct fxgmac_pdata *pdata, + struct fxgmac_desc_data *desc_data, + unsigned int index); }; struct fxgmac_hw_ops { @@ -455,9 +462,9 @@ struct fxgmac_hw_ops { int (*exit)(struct fxgmac_pdata *pdata); void (*save_nonstick_reg)(struct fxgmac_pdata *pdata); void (*restore_nonstick_reg)(struct fxgmac_pdata *pdata); - int (*set_gmac_register)(struct fxgmac_pdata *pdata, u8 *address, + int (*set_gmac_register)(struct fxgmac_pdata *pdata, IOMEM address, unsigned int data); - u32 (*get_gmac_register)(struct fxgmac_pdata *pdata, u8 *address); + u32 (*get_gmac_register)(struct fxgmac_pdata *pdata, IOMEM address); void (*esd_restore_pcie_cfg)(struct fxgmac_pdata *pdata); int (*tx_complete)(struct fxgmac_dma_desc *dma_desc); @@ -483,6 +490,7 @@ struct fxgmac_hw_ops { u32 intid); bool (*enable_mgm_interrupt)(struct fxgmac_pdata *pdata); bool (*disable_mgm_interrupt)(struct fxgmac_pdata *pdata); + int (*dismiss_all_int)(struct fxgmac_pdata *pdata); void (*dev_xmit)(struct fxgmac_channel *channel); int (*dev_read)(struct fxgmac_channel *channel); @@ -504,18 +512,14 @@ struct fxgmac_hw_ops { bool link_up_wait_to_complete); /* For descriptor related operation */ - void (*tx_desc_init)(struct fxgmac_channel *channel); - void (*rx_desc_init)(struct fxgmac_channel *channel); - void (*tx_desc_reset)(struct fxgmac_desc_data *desc_data); - void (*rx_desc_reset)(struct fxgmac_pdata *pdata, - struct fxgmac_desc_data *desc_data, - unsigned int index); + // void (*tx_desc_init)(struct fxgmac_channel *channel); + // void (*rx_desc_init)(struct fxgmac_channel *channel); + // void (*tx_desc_reset)(struct fxgmac_desc_data *desc_data); + // void (*rx_desc_reset)(struct fxgmac_pdata *pdata, + // struct fxgmac_desc_data *desc_data, + // unsigned int index); int (*is_last_desc)(struct fxgmac_dma_desc *dma_desc); int (*is_context_desc)(struct fxgmac_dma_desc *dma_desc); - void (*tx_start_xmit)(struct fxgmac_channel *channel, - struct fxgmac_ring *ring); - void (*set_pattern_data)(struct fxgmac_pdata *pdata); - void (*config_wol)(struct fxgmac_pdata *pdata, int en); /* For Flow Control */ int (*config_tx_flow_control)(struct fxgmac_pdata *pdata); @@ -579,6 +583,7 @@ struct fxgmac_hw_ops { const u32 *table); /*For Offload*/ +#ifdef FXGMAC_POWER_MANAGEMENT void (*set_arp_offload)(struct fxgmac_pdata *pdata, unsigned char *ip_addr); int (*enable_arp_offload)(struct fxgmac_pdata *pdata); @@ -609,7 +614,7 @@ struct fxgmac_hw_ops { int (*set_wake_pattern_mask)(struct fxgmac_pdata *pdata, u32 filter_index, u8 register_index, u32 Data); -#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN +#if FUXI_PM_WPI_READ_FEATURE_EN void (*get_wake_packet_indication)(struct fxgmac_pdata *pdata, int *wake_reason, u32 *wake_pattern_number, @@ -617,6 +622,7 @@ struct fxgmac_hw_ops { u32 *packet_size); void (*enable_wake_packet_indication)(struct fxgmac_pdata *pdata, int en); +#endif #endif void (*reset_phy)(struct fxgmac_pdata *pdata); @@ -630,7 +636,7 @@ struct fxgmac_hw_ops { void (*enable_phy_sleep)(struct fxgmac_pdata *pdata); void (*phy_green_ethernet)(struct fxgmac_pdata *pdata); void (*phy_eee_feature)(struct fxgmac_pdata *pdata); - int (*get_ephy_state)(struct fxgmac_pdata *pdata); + u32 (*get_ephy_state)(struct fxgmac_pdata *pdata); int (*write_ephy_reg)(struct fxgmac_pdata *pdata, u32 val, u32 data); int (*read_ephy_reg)(struct fxgmac_pdata *pdata, u32 val, u32 *data); int (*set_ephy_autoneg_advertise)(struct fxgmac_pdata *pdata, @@ -701,15 +707,6 @@ struct fxgmac_hw_ops { void (*trigger_pcie)( struct fxgmac_pdata *pdata, u32 code); /* To trigger pcie sniffer for analysis. */ -#ifdef DPDK - int (*phy_init)(struct fxgmac_pdata *); - int (*phy_start)(struct fxgmac_pdata *); - void (*phy_stop)(struct fxgmac_pdata *); - void (*phy_status)(struct fxgmac_pdata *); - void (*an_isr)( - struct fxgmac_pdata - *); /* phy_if->an_isr For single interrupt support */ -#endif }; /* This structure contains flags that indicate what hardware features @@ -915,6 +912,20 @@ struct fxgmac_pdata { #define FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN 1 #define FXGMAC_FLAG_LEGACY_NAPI_FREE_POS 30 /* bit30 */ #define FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN 1 +#define FXGMAC_FLAG_MISC_IRQ_FREE_POS 29 +#define FXGMAC_FLAG_MISC_IRQ_FREE_LEN 1 +#define FXGMAC_FLAG_MISC_NAPI_FREE_POS 28 +#define FXGMAC_FLAG_MISC_NAPI_FREE_LEN 1 +#define FXGMAC_FLAG_TX_IRQ_FREE_POS 27 +#define FXGMAC_FLAG_TX_IRQ_FREE_LEN 1 +#define FXGMAC_FLAG_TX_NAPI_FREE_POS 26 +#define FXGMAC_FLAG_TX_NAPI_FREE_LEN 1 +#define FXGMAC_FLAG_RX_IRQ_FREE_POS 22 +#define FXGMAC_FLAG_RX_IRQ_FREE_LEN 4 +#define FXGMAC_FLAG_PER_CHAN_RX_IRQ_FREE_LEN 1 +#define FXGMAC_FLAG_RX_NAPI_FREE_POS 18 +#define FXGMAC_FLAG_RX_NAPI_FREE_LEN 4 +#define FXGMAC_FLAG_PER_CHAN_RX_NAPI_FREE_LEN 1 void fxgmac_init_desc_ops(struct fxgmac_desc_ops *desc_ops); void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops); diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h index 1a40267e1fa2e..38c27a9d45973 100644 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h @@ -30,8 +30,9 @@ struct fxgmac_ring; struct fxgmac_pdata; +struct fxgmac_channel; -#define FXGMAC_DRV_VERSION "1.0.27" +#define FXGMAC_DRV_VERSION "1.0.28" #define PCIE_LP_ASPM_L0S 1 #define PCIE_LP_ASPM_L1 2 @@ -55,12 +56,6 @@ struct fxgmac_pdata; #define RSS_Q_COUNT 4 #define FXGMAC_TX_HANG_TIMER_EN 0 -/* only for debug. for normal run, pls keep them both 0 - * 0: use default tx q; other: specify txq-1: 1 txq; - */ -#define FXGMAC_NUM_OF_TX_Q_USED 0 -/* 1 to enable a dummy tx, ie, no tail for gmac; */ -#define FXGMAC_DUMMY_TX_DEBUG 0 /* 1 to trigger(write reg 0x1000) for sniffer stop */ #define FXGMAC_TRIGGER_TX_HANG 0 @@ -70,12 +65,6 @@ struct fxgmac_pdata; #define FXGMAC_TX_HANG_CHECH_DIRTY 0 #endif -/* 1:poll tx of 4 channels; 0: since only 1 tx channel supported in this - * version, poll ch 0 always. - */ - -#define FXGMAC_FULL_TX_CHANNEL 0 - #ifdef CONFIG_ARM64 /* when you want to run this driver on 64bit arm, you should open this, * otherwise dma's mask cannot be set successfully. @@ -135,7 +124,37 @@ struct fxgmac_pdata; #define FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED 1 #define FUXI_MISC_INT_HANDLE_FEATURE_EN 1 -#define HAVE_FXGMAC_DEBUG_FS +#define FXGMAC_ESD_RESTORE_PCIE_CFG + +#define FXGMAC_FIX_FT_D2000_PLATFORM_WOL_ISSUE 1 + +#define FXGMAC_WOL_INTEGRATED_WOL_PARAMETER + +#define FXGMAC_LINK_SPEED_CHECK_PHY_LINK + +#define FXGMAC_FLUSH_TX_CHECK_ENABLED + +#define FXGMAC_POWER_MANAGEMENT + +#define FXGMAC_INTERRUPT_TX_INTERVAL + +#define FXGMAC_INTERRUPT_RX_INTERVAL + +#define FXGMAC_WAIT_TX_STOP + +#define FXGMAC_WAIT_RX_STOP_BY_PRXQ_RXQSTS + +#define FXGMAC_USE_DEFAULT_RSS_KEY_TBALE + +#define FXGMAC_RX_VLAN_FILTERING (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) + +#define FXGMAC_NETDEV_PR_MODE ((pdata->netdev->flags & IFF_PROMISC) != 0) + +#define FXGMAC_NETDEV_AM_MODE ((pdata->netdev->flags & IFF_ALLMULTI) != 0) + +#define FXGMAC_RX_CHECKSUM (pdata->netdev->features & NETIF_F_RXCSUM) + +/* #define HAVE_FXGMAC_DEBUG_FS */ #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *)0)->MEMBER)) @@ -223,7 +242,7 @@ struct fxgmac_pdata; #define DumpLine(_p, _cbLine, _fAddress, _ulGroup) #ifndef FXGMAC_DEBUG -#define FXGMAC_DEBUG +/* #define FXGMAC_DEBUG */ #endif /* For debug prints */ @@ -262,8 +281,8 @@ struct fxgmac_pdata; #define FXGMAC_SET_MAC_DATA 0x10012 #define FXGMAC_GET_SUBSYS_ID 0x10013 #define FXGMAC_SET_SUBSYS_ID 0x10014 -#define FXGMAC_GET_GMAC_REG 0x10015 -#define FXGMAC_SET_GMAC_REG 0x10016 +#define FXGMAC_GET_REG 0x10015 +#define FXGMAC_SET_REG 0x10016 #define FXGMAC_GET_PHY_REG 0x10017 #define FXGMAC_SET_PHY_REG 0x10018 #define FXGMAC_EPHYSTATISTICS 0x10019 @@ -292,6 +311,11 @@ struct fxgmac_pdata; #define PCI_CAP_ID_MSIX_ENABLE_POS 0x1F #define PCI_CAP_ID_MSIX_ENABLE_LEN 0x1 +#define FXGMAC_IRQ_ENABLE 0x1 +#define FXGMAC_IRQ_DISABLE 0x0 +#define FXGMAC_NAPI_ENABLE 0x1 +#define FXGMAC_NAPI_DISABLE 0x0 + #ifndef fallthrough #if __has_attribute(__fallthrough__) # define fallthrough __attribute__((__fallthrough__)) @@ -300,6 +324,19 @@ struct fxgmac_pdata; #endif #endif +#define PHY_POWER_DOWN 1 +#define PHY_POWER_UP 0 + +#define FXGMAC_MMC_IER_ALL_DEFAULT 0 + +/* #define FXGMAC_ESD_CHECK_ENABLED */ +#ifdef FXGMAC_ESD_CHECK_ENABLED +#define FXGMAC_ESD_INTERVAL (5 * HZ) +#define FXGMAC_ESD_ERROR_THRESHOLD ((u64)4000000000) +#define FXGMAC_PCIE_LINK_DOWN 0xFFFFFFFF +#define FXGMAC_PCIE_RECOVER_TIMES 5000 +#define FXGMAC_PCIE_IO_MEM_MASTER_ENABLE 0x7 +#endif #pragma pack(1) /* it's better to make this struct's size to 128byte. */ @@ -322,17 +359,6 @@ struct pattern_packet{ }; #pragma pack() -typedef enum { - CURRENT_STATE_SHUTDOWN = 0, - CURRENT_STATE_RESUME = 1, - CURRENT_STATE_INIT = 2, - CURRENT_STATE_SUSPEND = 3, - CURRENT_STATE_CLOSE = 4, - CURRENT_STATE_OPEN = 5, - CURRENT_STATE_RESTART = 6, - CURRENT_STATE_REMOVE = 7, -} CURRENT_STATE; - typedef dma_addr_t DMA_ADDR_T; typedef enum pkt_hash_types RSS_HASH_TYPE; typedef void __iomem *IOMEM; @@ -425,6 +451,36 @@ typedef struct ext_command_data { u32 val2; } CMD_DATA; +enum fxgmac_task_flag { + FXGMAC_FLAG_TASK_DOWN = 0, + FXGMAC_FLAG_TASK_RESET_PENDING, + FXGMAC_FLAG_TASK_ESD_CHECK_PENDING, + FXGMAC_FLAG_TASK_LINKCHG_CHECK_PENDING, + FXGMAC_FLAG_TASK_MAX +}; + +typedef struct fxgmac_esd_stats { + u32 tx_abort_excess_collisions; + u32 tx_dma_underrun; + u32 tx_lost_crs; + u32 tx_late_collisions; + u32 rx_crc_errors; + u32 rx_align_errors; + u32 rx_runt_errors; + u32 single_collisions; + u32 multi_collisions; + u32 tx_deferred_frames; +} FXGMAC_ESD_STATS; + +typedef enum fxgmac_dev_state { + FXGMAC_DEV_OPEN = 0x0, + FXGMAC_DEV_CLOSE = 0x1, + FXGMAC_DEV_STOP = 0x2, + FXGMAC_DEV_START = 0x3, + FXGMAC_DEV_SUSPEND = 0x4, + FXGMAC_DEV_RESUME = 0x5, + FXGMAC_DEV_PROBE = 0xFF, +} DEV_STATE; typedef struct fxgmac_pdata_of_platform { u32 cfg_pci_cmd; u32 cfg_cache_line_size; @@ -438,20 +494,26 @@ typedef struct fxgmac_pdata_of_platform { u32 cfg_msix_capability; struct work_struct restart_work; +#ifdef FXGMAC_ESD_CHECK_ENABLED + struct delayed_work esd_work; + FXGMAC_ESD_STATS esd_stats; + DECLARE_BITMAP(task_flags, FXGMAC_FLAG_TASK_MAX); +#endif u32 int_flags; /* legacy, msi or msix */ - int phy_irq; + int misc_irq; #ifdef CONFIG_PCI_MSI struct msix_entry *msix_entries; #endif /* power management and wol*/ - u32 wol; /* wol options */ - unsigned long powerstate; /* power state */ - unsigned int ns_offload_tab_idx; /* for ns-offload table. 2 entries supported. */ - CURRENT_STATE current_state; + u32 wol; + unsigned long powerstate; + /*for ns-offload table. 2 entries supported. */ + unsigned int ns_offload_tab_idx; netdev_features_t netdev_features; struct napi_struct napi; - struct napi_struct napi_phy; + struct napi_struct napi_misc; + char misc_irq_name[IFNAMSIZ + 32]; u32 mgm_intctrl_val; bool phy_link; bool fxgmac_test_tso_flag; @@ -466,6 +528,8 @@ typedef struct fxgmac_pdata_of_platform { struct dentry *fxgmac_dbg_root; char fxgmac_dbg_netdev_ops_buf[FXGMAC_NETDEV_OPS_BUF_LEN]; #endif + DEV_STATE dev_state; + struct mutex mutex; } FXGMAC_PDATA_OF_PLATFORM; void fxgmac_print_pkt(struct net_device *netdev, struct sk_buff *skb, @@ -490,6 +554,7 @@ int fxgmac_ephy_autoneg_ability_get(struct fxgmac_pdata *pdata, int fxgmac_ephy_status_get(struct fxgmac_pdata *pdata, int *speed, int *duplex, int *ret_link, int *media); int fxgmac_ephy_soft_reset(struct fxgmac_pdata *pdata); +void fxgmac_phy_force_mode(struct fxgmac_pdata *pdata); void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed); void fxgmac_phy_force_duplex(struct fxgmac_pdata *pdata, int duplex); void fxgmac_phy_force_autoneg(struct fxgmac_pdata *pdata, int autoneg); @@ -512,4 +577,14 @@ void fxgmac_stop(struct fxgmac_pdata *pdata); void fxgmac_free_rx_data(struct fxgmac_pdata *pdata); void fxgmac_free_tx_data(struct fxgmac_pdata *pdata); +void fxgmac_tx_start_xmit(struct fxgmac_channel *channel, struct fxgmac_ring *ring); +void fxgmac_dev_xmit(struct fxgmac_channel *channel); +int fxgmac_dev_read(struct fxgmac_channel *channel); + +void fxgmac_config_wol(struct fxgmac_pdata *pdata, int en); +void fxgmac_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx); + +void fxgmac_lock(struct fxgmac_pdata *pdata); +void fxgmac_unlock(struct fxgmac_pdata *pdata); + #endif /* __FUXI_OS_H__ */