@@ -1204,6 +1204,71 @@ static void fxgmac_rx_mmc_int(struct fxgmac_pdata *yt)
stats->rxcontrolframe_g += rd32_mac(yt, MMC_RXCONTROLFRAME_G);
}
+static void fxgmac_read_mmc_stats(struct fxgmac_pdata *yt)
+{
+ struct fxgmac_stats *stats = &yt->stats;
+
+ stats->txoctetcount_gb += rd32_mac(yt, MMC_TXOCTETCOUNT_GB_LO);
+ stats->txframecount_gb += rd32_mac(yt, MMC_TXFRAMECOUNT_GB_LO);
+ stats->txbroadcastframes_g += rd32_mac(yt, MMC_TXBROADCASTFRAMES_G_LO);
+ stats->txmulticastframes_g += rd32_mac(yt, MMC_TXMULTICASTFRAMES_G_LO);
+ stats->tx64octets_gb += rd32_mac(yt, MMC_TX64OCTETS_GB_LO);
+ stats->tx65to127octets_gb += rd32_mac(yt, MMC_TX65TO127OCTETS_GB_LO);
+ stats->tx128to255octets_gb += rd32_mac(yt, MMC_TX128TO255OCTETS_GB_LO);
+ stats->tx256to511octets_gb += rd32_mac(yt, MMC_TX256TO511OCTETS_GB_LO);
+ stats->tx512to1023octets_gb +=
+ rd32_mac(yt, MMC_TX512TO1023OCTETS_GB_LO);
+ stats->tx1024tomaxoctets_gb +=
+ rd32_mac(yt, MMC_TX1024TOMAXOCTETS_GB_LO);
+ stats->txunicastframes_gb += rd32_mac(yt, MMC_TXUNICASTFRAMES_GB_LO);
+ stats->txmulticastframes_gb +=
+ rd32_mac(yt, MMC_TXMULTICASTFRAMES_GB_LO);
+ stats->txbroadcastframes_g += rd32_mac(yt, MMC_TXBROADCASTFRAMES_GB_LO);
+ stats->txunderflowerror += rd32_mac(yt, MMC_TXUNDERFLOWERROR_LO);
+ stats->txsinglecollision_g += rd32_mac(yt, MMC_TXSINGLECOLLISION_G);
+ stats->txmultiplecollision_g += rd32_mac(yt, MMC_TXMULTIPLECOLLISION_G);
+ stats->txdeferredframes += rd32_mac(yt, MMC_TXDEFERREDFRAMES);
+ stats->txlatecollisionframes += rd32_mac(yt, MMC_TXLATECOLLISIONFRAMES);
+ stats->txexcessivecollisionframes +=
+ rd32_mac(yt, MMC_TXEXCESSIVECOLLSIONFRAMES);
+ stats->txcarriererrorframes += rd32_mac(yt, MMC_TXCARRIERERRORFRAMES);
+ stats->txoctetcount_g += rd32_mac(yt, MMC_TXOCTETCOUNT_G_LO);
+ stats->txframecount_g += rd32_mac(yt, MMC_TXFRAMECOUNT_G_LO);
+ stats->txexcessivedeferralerror +=
+ rd32_mac(yt, MMC_TXEXCESSIVEDEFERRALERROR);
+ stats->txpauseframes += rd32_mac(yt, MMC_TXPAUSEFRAMES_LO);
+ stats->txvlanframes_g += rd32_mac(yt, MMC_TXVLANFRAMES_G_LO);
+ stats->txoversize_g += rd32_mac(yt, MMC_TXOVERSIZEFRAMES);
+ stats->rxframecount_gb += rd32_mac(yt, MMC_RXFRAMECOUNT_GB_LO);
+ stats->rxoctetcount_gb += rd32_mac(yt, MMC_RXOCTETCOUNT_GB_LO);
+ stats->rxoctetcount_g += rd32_mac(yt, MMC_RXOCTETCOUNT_G_LO);
+ stats->rxbroadcastframes_g += rd32_mac(yt, MMC_RXBROADCASTFRAMES_G_LO);
+ stats->rxmulticastframes_g += rd32_mac(yt, MMC_RXMULTICASTFRAMES_G_LO);
+ stats->rxcrcerror += rd32_mac(yt, MMC_RXCRCERROR_LO);
+ stats->rxalignerror += rd32_mac(yt, MMC_RXALIGNERROR);
+ stats->rxrunterror += rd32_mac(yt, MMC_RXRUNTERROR);
+ stats->rxjabbererror += rd32_mac(yt, MMC_RXJABBERERROR);
+ stats->rxundersize_g += rd32_mac(yt, MMC_RXUNDERSIZE_G);
+ stats->rxoversize_g += rd32_mac(yt, MMC_RXOVERSIZE_G);
+ stats->rx64octets_gb += rd32_mac(yt, MMC_RX64OCTETS_GB_LO);
+ stats->rx65to127octets_gb += rd32_mac(yt, MMC_RX65TO127OCTETS_GB_LO);
+ stats->rx128to255octets_gb += rd32_mac(yt, MMC_RX128TO255OCTETS_GB_LO);
+ stats->rx256to511octets_gb += rd32_mac(yt, MMC_RX256TO511OCTETS_GB_LO);
+ stats->rx512to1023octets_gb +=
+ rd32_mac(yt, MMC_RX512TO1023OCTETS_GB_LO);
+ stats->rx1024tomaxoctets_gb +=
+ rd32_mac(yt, MMC_RX1024TOMAXOCTETS_GB_LO);
+ stats->rxunicastframes_g += rd32_mac(yt, MMC_RXUNICASTFRAMES_G_LO);
+ stats->rxlengtherror += rd32_mac(yt, MMC_RXLENGTHERROR_LO);
+ stats->rxoutofrangetype += rd32_mac(yt, MMC_RXOUTOFRANGETYPE_LO);
+ stats->rxpauseframes += rd32_mac(yt, MMC_RXPAUSEFRAMES_LO);
+ stats->rxfifooverflow += rd32_mac(yt, MMC_RXFIFOOVERFLOW_LO);
+ stats->rxvlanframes_gb += rd32_mac(yt, MMC_RXVLANFRAMES_GB_LO);
+ stats->rxwatchdogerror += rd32_mac(yt, MMC_RXWATCHDOGERROR);
+ stats->rxreceiveerrorframe += rd32_mac(yt, MMC_RXRECEIVEERRORFRAME);
+ stats->rxcontrolframe_g += rd32_mac(yt, MMC_RXCONTROLFRAME_G);
+}
+
static void fxgmac_config_mmc(struct fxgmac_pdata *pdata)
{
u32 val;
@@ -2610,6 +2675,10 @@ void fxgmac_hw_ops_init(struct fxgmac_hw_ops *hw_ops)
/* RX coalescing */
hw_ops->config_rx_coalesce = fxgmac_config_rx_coalesce;
hw_ops->usec_to_riwt = fxgmac_usec_to_riwt;
+
+ /* MMC statistics support */
+ hw_ops->read_mmc_stats = fxgmac_read_mmc_stats;
+
/* Receive Side Scaling */
hw_ops->enable_rss = fxgmac_enable_rss;
hw_ops->disable_rss = fxgmac_disable_rss;
@@ -1015,6 +1015,129 @@ static int fxgmac_close(struct net_device *netdev)
return 0;
}
+static void fxgmac_dump_state(struct fxgmac_pdata *pdata)
+{
+ struct fxgmac_channel *channel = pdata->channel_head;
+ struct fxgmac_stats *pstats = &pdata->stats;
+ struct fxgmac_ring *ring;
+
+ ring = &channel->tx_ring[0];
+ yt_err(pdata, "Tx descriptor info:\n");
+ yt_err(pdata, "Tx cur = 0x%x\n", ring->cur);
+ yt_err(pdata, "Tx dirty = 0x%x\n", ring->dirty);
+ yt_err(pdata, "Tx dma_desc_head = %pad\n", &ring->dma_desc_head);
+ yt_err(pdata, "Tx desc_data_head = %pad\n", &ring->desc_data_head);
+
+ for (u32 i = 0; i < pdata->channel_count; i++, channel++) {
+ ring = &channel->rx_ring[0];
+ yt_err(pdata, "Rx[%d] descriptor info:\n", i);
+ yt_err(pdata, "Rx cur = 0x%x\n", ring->cur);
+ yt_err(pdata, "Rx dirty = 0x%x\n", ring->dirty);
+ yt_err(pdata, "Rx dma_desc_head = %pad\n",
+ &ring->dma_desc_head);
+ yt_err(pdata, "Rx desc_data_head = %pad\n",
+ &ring->desc_data_head);
+ }
+
+ yt_err(pdata, "Device Registers:\n");
+ yt_err(pdata, "MAC_ISR = %08x\n", rd32_mac(pdata, MAC_ISR));
+ yt_err(pdata, "MAC_IER = %08x\n", rd32_mac(pdata, MAC_IER));
+ yt_err(pdata, "MMC_RISR = %08x\n", rd32_mac(pdata, MMC_RISR));
+ yt_err(pdata, "MMC_RIER = %08x\n", rd32_mac(pdata, MMC_RIER));
+ yt_err(pdata, "MMC_TISR = %08x\n", rd32_mac(pdata, MMC_TISR));
+ yt_err(pdata, "MMC_TIER = %08x\n", rd32_mac(pdata, MMC_TIER));
+
+ yt_err(pdata, "EPHY_CTRL = %04x\n", rd32_mem(pdata, EPHY_CTRL));
+ yt_err(pdata, "MGMT_INT_CTRL0 = %04x\n",
+ rd32_mem(pdata, MGMT_INT_CTRL0));
+ yt_err(pdata, "LPW_CTRL = %04x\n", rd32_mem(pdata, LPW_CTRL));
+ yt_err(pdata, "MSIX_TBL_MASK = %04x\n", rd32_mem(pdata, MSIX_TBL_MASK));
+
+ yt_err(pdata, "Dump nonstick regs:\n");
+ for (u32 i = GLOBAL_CTRL0; i < MSI_PBA; i += 4)
+ yt_err(pdata, "[%d] = %04x\n", i / 4, rd32_mem(pdata, i));
+
+ pdata->hw_ops.read_mmc_stats(pdata);
+
+ yt_err(pdata, "Dump TX counters:\n");
+ yt_err(pdata, "tx_packets %lld\n", pstats->txframecount_gb);
+ yt_err(pdata, "tx_errors %lld\n",
+ pstats->txframecount_gb - pstats->txframecount_g);
+ yt_err(pdata, "tx_multicastframes_errors %lld\n",
+ pstats->txmulticastframes_gb - pstats->txmulticastframes_g);
+ yt_err(pdata, "tx_broadcastframes_errors %lld\n",
+ pstats->txbroadcastframes_gb - pstats->txbroadcastframes_g);
+
+ yt_err(pdata, "txunderflowerror %lld\n", pstats->txunderflowerror);
+ yt_err(pdata, "txdeferredframes %lld\n",
+ pstats->txdeferredframes);
+ yt_err(pdata, "txlatecollisionframes %lld\n",
+ pstats->txlatecollisionframes);
+ yt_err(pdata, "txexcessivecollisionframes %lld\n",
+ pstats->txexcessivecollisionframes);
+ yt_err(pdata, "txcarriererrorframes %lld\n",
+ pstats->txcarriererrorframes);
+ yt_err(pdata, "txexcessivedeferralerror %lld\n",
+ pstats->txexcessivedeferralerror);
+
+ yt_err(pdata, "txsinglecollision_g %lld\n",
+ pstats->txsinglecollision_g);
+ yt_err(pdata, "txmultiplecollision_g %lld\n",
+ pstats->txmultiplecollision_g);
+ yt_err(pdata, "txoversize_g %lld\n", pstats->txoversize_g);
+
+ yt_err(pdata, "Dump RX counters:\n");
+ yt_err(pdata, "rx_packets %lld\n", pstats->rxframecount_gb);
+ yt_err(pdata, "rx_errors %lld\n",
+ pstats->rxframecount_gb - pstats->rxbroadcastframes_g -
+ pstats->rxmulticastframes_g - pstats->rxunicastframes_g);
+
+ yt_err(pdata, "rx_crc_errors %lld\n", pstats->rxcrcerror);
+ yt_err(pdata, "rxalignerror %lld\n", pstats->rxalignerror);
+ yt_err(pdata, "rxrunterror %lld\n", pstats->rxrunterror);
+ yt_err(pdata, "rxjabbererror %lld\n", pstats->rxjabbererror);
+ yt_err(pdata, "rx_length_errors %lld\n", pstats->rxlengtherror);
+ yt_err(pdata, "rxoutofrangetype %lld\n", pstats->rxoutofrangetype);
+ yt_err(pdata, "rx_fifo_errors %lld\n", pstats->rxfifooverflow);
+ yt_err(pdata, "rxwatchdogerror %lld\n", pstats->rxwatchdogerror);
+ yt_err(pdata, "rxreceiveerrorframe %lld\n",
+ pstats->rxreceiveerrorframe);
+
+ yt_err(pdata, "rxbroadcastframes_g %lld\n",
+ pstats->rxbroadcastframes_g);
+ yt_err(pdata, "rxmulticastframes_g %lld\n",
+ pstats->rxmulticastframes_g);
+ yt_err(pdata, "rxundersize_g %lld\n", pstats->rxundersize_g);
+ yt_err(pdata, "rxoversize_g %lld\n", pstats->rxoversize_g);
+ yt_err(pdata, "rxunicastframes_g %lld\n", pstats->rxunicastframes_g);
+ yt_err(pdata, "rxcontrolframe_g %lld\n", pstats->rxcontrolframe_g);
+
+ yt_err(pdata, "Dump Extra counters:\n");
+ yt_err(pdata, "tx_tso_packets %lld\n", pstats->tx_tso_packets);
+ yt_err(pdata, "rx_split_header_packets %lld\n",
+ pstats->rx_split_header_packets);
+ yt_err(pdata, "tx_process_stopped %lld\n", pstats->tx_process_stopped);
+ yt_err(pdata, "rx_process_stopped %lld\n", pstats->rx_process_stopped);
+ yt_err(pdata, "tx_buffer_unavailable %lld\n",
+ pstats->tx_buffer_unavailable);
+ yt_err(pdata, "rx_buffer_unavailable %lld\n",
+ pstats->rx_buffer_unavailable);
+ yt_err(pdata, "fatal_bus_error %lld\n", pstats->fatal_bus_error);
+ yt_err(pdata, "napi_poll_isr %lld\n", pstats->napi_poll_isr);
+ yt_err(pdata, "napi_poll_txtimer %lld\n", pstats->napi_poll_txtimer);
+ yt_err(pdata, "ephy_poll_timer_cnt %lld\n",
+ pstats->ephy_poll_timer_cnt);
+ yt_err(pdata, "mgmt_int_isr %lld\n", pstats->mgmt_int_isr);
+}
+
+static void fxgmac_tx_timeout(struct net_device *netdev, unsigned int unused)
+{
+ struct fxgmac_pdata *pdata = netdev_priv(netdev);
+
+ fxgmac_dump_state(pdata);
+ schedule_work(&pdata->restart_work);
+}
+
#define EFUSE_FISRT_UPDATE_ADDR 255
#define EFUSE_SECOND_UPDATE_ADDR 209
#define EFUSE_MAX_ENTRY 39
@@ -2046,6 +2169,41 @@ static int fxgmac_set_mac_address(struct net_device *netdev, void *addr)
return 0;
}
+static int fxgmac_change_mtu(struct net_device *netdev, int mtu)
+{
+ struct fxgmac_pdata *pdata = netdev_priv(netdev);
+ int old_mtu = netdev->mtu;
+ int ret;
+
+ mutex_lock(&pdata->mutex);
+ fxgmac_stop(pdata);
+ fxgmac_free_tx_data(pdata);
+
+ /* We must unmap rx desc's dma before we change rx_buf_size.
+ * Becaues the size of the unmapped DMA is set according to rx_buf_size
+ */
+ fxgmac_free_rx_data(pdata);
+ pdata->jumbo = mtu > ETH_DATA_LEN ? 1 : 0;
+ ret = fxgmac_calc_rx_buf_size(pdata, mtu);
+ if (ret < 0)
+ return ret;
+
+ pdata->rx_buf_size = ret;
+ netdev->mtu = mtu;
+
+ if (netif_running(netdev))
+ fxgmac_start(pdata);
+
+ netdev_update_features(netdev);
+
+ mutex_unlock(&pdata->mutex);
+
+ yt_dbg(pdata, "fxgmac,set MTU from %d to %d. min, max=(%d,%d)\n",
+ old_mtu, netdev->mtu, netdev->min_mtu, netdev->max_mtu);
+
+ return 0;
+}
+
static int fxgmac_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
u16 vid)
{
@@ -2169,7 +2327,9 @@ static const struct net_device_ops fxgmac_netdev_ops = {
.ndo_open = fxgmac_open,
.ndo_stop = fxgmac_close,
.ndo_start_xmit = fxgmac_xmit,
+ .ndo_tx_timeout = fxgmac_tx_timeout,
.ndo_get_stats64 = fxgmac_get_stats64,
+ .ndo_change_mtu = fxgmac_change_mtu,
.ndo_set_mac_address = fxgmac_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = fxgmac_vlan_rx_add_vid,
Implement following callback function .ndo_tx_timeout .ndo_change_mtu The .ndo_tx_timeout function also will call fxgmac_dump_state to dump nessary debug information. Signed-off-by: Frank Sae <Frank.Sae@motor-comm.com> --- .../net/ethernet/motorcomm/yt6801/yt6801_hw.c | 69 ++++++++ .../ethernet/motorcomm/yt6801/yt6801_net.c | 160 ++++++++++++++++++ 2 files changed, 229 insertions(+)