[PATCH net-next v2 12/21] motorcomm:yt6801: Implement .ndo_tx_timeout and .ndo_change_mtu functions

Frank Sae posted 21 patches 4 days, 2 hours ago
[PATCH net-next v2 12/21] motorcomm:yt6801: Implement .ndo_tx_timeout and .ndo_change_mtu functions
Posted by Frank Sae 4 days, 2 hours ago
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(+)

diff --git a/drivers/net/ethernet/motorcomm/yt6801/yt6801_hw.c b/drivers/net/ethernet/motorcomm/yt6801/yt6801_hw.c
index 791dd69b7..a70fa4ede 100644
--- a/drivers/net/ethernet/motorcomm/yt6801/yt6801_hw.c
+++ b/drivers/net/ethernet/motorcomm/yt6801/yt6801_hw.c
@@ -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;
diff --git a/drivers/net/ethernet/motorcomm/yt6801/yt6801_net.c b/drivers/net/ethernet/motorcomm/yt6801/yt6801_net.c
index ed65c9cc9..c5c13601e 100644
--- a/drivers/net/ethernet/motorcomm/yt6801/yt6801_net.c
+++ b/drivers/net/ethernet/motorcomm/yt6801/yt6801_net.c
@@ -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,
-- 
2.34.1
Re: [PATCH net-next v2 12/21] motorcomm:yt6801: Implement .ndo_tx_timeout and .ndo_change_mtu functions
Posted by Andrew Lunn 1 day, 13 hours ago
> +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);

I don't see anything here handling pause when changing to/from jumbo.
Is it hiding somewhere?

	Andrew