Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d597541 authored by Sneh Shah's avatar Sneh Shah
Browse files

net: stmmac: Add support for panic notifier in stmmac



Add panic notifier to debug kernel crash.

Change-Id: I56401bca3102331b9b26112795f54d351c8807bf
Signed-off-by: default avatarSneh Shah <snehshah@codeaurora.org>
parent bdd6da44
Loading
Loading
Loading
Loading
+123 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "dwmac-qcom-ethqos.h"
#include "stmmac_ptp.h"
#include "dwmac-qcom-ipa-offload.h"
#include "dwmac-qcom-ipa.h"

#define PHY_LOOPBACK_1000 0x4140
#define PHY_LOOPBACK_100 0x6100
@@ -2575,6 +2576,126 @@ static void ethqos_get_cv2x_dt(struct qcom_ethqos *ethqos,
	}
}

inline u32 qcom_ethqos_rgmii_io_macro_num_of_regs(u32 emac_hw_version)
{
	switch (emac_hw_version) {
	case EMAC_HW_v2_0_0:
		return 27;
	case EMAC_HW_v2_1_0:
		return 27;
	case EMAC_HW_v2_1_1:
		return 27;
	case EMAC_HW_v2_1_2:
		return 27;
	case EMAC_HW_v2_2_0:
		return 27;
	case EMAC_HW_v2_3_0:
		return 28;
	case EMAC_HW_v2_3_1:
		return 27;
	case EMAC_HW_v2_3_2:
		return 29;
	case EMAC_HW_NONE:
	default:
		return 0;
	}
}

static void ethqos_dma_desc_stats_read(struct qcom_ethqos *ethqos)
{
	int qinx;

	struct platform_device *pdev = ethqos->pdev;
	struct net_device *dev = platform_get_drvdata(pdev);
	struct stmmac_priv *priv = netdev_priv(dev);
	u32 tx_count = priv->plat->tx_queues_to_use;
	u32 rx_count = priv->plat->rx_queues_to_use;

	ETHQOSDBG("Enter");
	ethqos->xstats.dma_ch_intr_status = readl_relaxed(DMA_ISR_RGOFFADDR);
	ethqos->xstats.dma_debug_status0 = readl_relaxed(DMA_DSR0_RGOFFADDR);
	ethqos->xstats.dma_debug_status1 = readl_relaxed(DMA_DSR1_RGOFFADDR);

	for (qinx = 0; qinx < tx_count; qinx++) {
		if (ethqos->ipa_enabled && qinx == IPA_DMA_TX_CH)
			continue;
		ethqos->xstats.dma_ch_status[qinx] =
		readl_relaxed(DMA_SR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_intr_enable[qinx] =
		readl_relaxed(DMA_IER_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_tx_control[qinx] =
		readl_relaxed(DMA_TCR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_txdesc_list_addr[qinx] =
		readl_relaxed(DMA_TDLAR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_txdesc_ring_len[qinx] =
		readl_relaxed(DMA_TDRLR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_curr_app_txdesc[qinx] =
		readl_relaxed(DMA_CHTDR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_txdesc_tail_ptr[qinx] =
		readl_relaxed(DMA_TDTP_TPDR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_curr_app_txbuf[qinx] =
		readl_relaxed(DMA_CHTBAR_RGOFFADDRESS(qinx));
	}

	for (qinx = 0; qinx < rx_count; qinx++) {
		if (ethqos->ipa_enabled && qinx == IPA_DMA_RX_CH)
			continue;
		ethqos->xstats.dma_ch_rx_control[qinx] =
		readl_relaxed(DMA_RCR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_rxdesc_list_addr[qinx] =
		readl_relaxed(DMA_RDLAR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_rxdesc_ring_len[qinx] =
		readl_relaxed(DMA_RDRLR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_curr_app_rxdesc[qinx] =
		readl_relaxed(DMA_CHRDR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_rxdesc_tail_ptr[qinx] =
		readl_relaxed(DMA_RDTP_RPDR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_curr_app_rxbuf[qinx] =
		readl_relaxed(DMA_CHRBAR_RGOFFADDRESS(qinx));
		ethqos->xstats.dma_ch_miss_frame_count[qinx] =
		readl_relaxed(DMA_CH_MISS_FRAME_CNT_RGOFFADDRESS(qinx));
	}
	ETHQOSDBG("Exit");
}

static int qcom_ethos_panic_notifier(struct notifier_block *this,
				     unsigned long event, void *ptr)
{
	u32 size_iomacro_regs;

	if (pethqos) {
		size_iomacro_regs =
		qcom_ethqos_rgmii_io_macro_num_of_regs(pethqos->emac_ver) * 4;
		ETHQOSINFO("pethqos 0x%p", pethqos);
		ethqos_dma_desc_stats_read(pethqos);

		pethqos->iommu_domain = stmmac_emb_smmu_ctx.iommu_domain;
		ETHQOSINFO("emac iommu domain 0x%p", pethqos->iommu_domain);

		pethqos->emac_reg_base_address =
		kzalloc(pethqos->emac_mem_size, GFP_KERNEL);
		ETHQOSINFO("emac register mem 0x%p", pethqos->emac_mem_base);
		if (pethqos->emac_mem_base)
			memcpy_fromio(pethqos->emac_reg_base_address,
				      pethqos->ioaddr,
				      pethqos->emac_mem_size);

		pethqos->rgmii_reg_base_address =
		kzalloc(size_iomacro_regs, GFP_KERNEL);
		ETHQOSINFO
		("rgmii register mem 0x%p", pethqos->rgmii_reg_base_address);
		if (pethqos->rgmii_reg_base_address)
			memcpy_fromio(pethqos->rgmii_reg_base_address,
				      pethqos->rgmii_base,
				      size_iomacro_regs);
	}
	return NOTIFY_DONE;
}

static struct notifier_block qcom_ethqos_panic_blk = {
	.notifier_call  = qcom_ethos_panic_notifier,
};

static int qcom_ethqos_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
@@ -2769,6 +2890,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
	if (ret)
		goto err_clk;

	atomic_notifier_chain_register(&panic_notifier_list,
				       &qcom_ethqos_panic_blk);
	rgmii_dump(ethqos);

	if (ethqos->emac_ver == EMAC_HW_v2_3_2) {
+33 −0
Original line number Diff line number Diff line
@@ -426,6 +426,32 @@ struct ethqos_io_macro {
	bool rx_dll_bypass;
};

struct ethqos_extra_dma_stats {
	/* DMA status registers for all channels [0-4] */
	unsigned long dma_ch_status[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_intr_enable[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_intr_status;
	unsigned long dma_debug_status0;
	unsigned long dma_debug_status1;

	/* RX DMA descriptor status registers for all channels [0-4] */
	unsigned long dma_ch_rx_control[MTL_MAX_RX_QUEUES];
	unsigned long dma_ch_rxdesc_list_addr[MTL_MAX_RX_QUEUES];
	unsigned long dma_ch_rxdesc_ring_len[MTL_MAX_RX_QUEUES];
	unsigned long dma_ch_curr_app_rxdesc[MTL_MAX_RX_QUEUES];
	unsigned long dma_ch_rxdesc_tail_ptr[MTL_MAX_RX_QUEUES];
	unsigned long dma_ch_curr_app_rxbuf[MTL_MAX_RX_QUEUES];
	unsigned long dma_ch_miss_frame_count[MTL_MAX_RX_QUEUES];

	/* TX DMA descriptors status for all channels [0-5] */
	unsigned long dma_ch_tx_control[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_txdesc_list_addr[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_txdesc_ring_len[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_curr_app_txdesc[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_txdesc_tail_ptr[MTL_MAX_TX_QUEUES];
	unsigned long dma_ch_curr_app_txbuf[MTL_MAX_TX_QUEUES];
};

struct qcom_ethqos {
	struct platform_device *pdev;
	void __iomem *rgmii_base;
@@ -438,6 +464,10 @@ struct qcom_ethqos {
	unsigned int speed;
	unsigned int vote_idx;

	struct iommu_domain *iommu_domain;
	unsigned int *emac_reg_base_address;
	unsigned int *rgmii_reg_base_address;

	int gpio_phy_intr_redirect;
	u32 phy_intr;
	/* Work struct for handling phy interrupt */
@@ -504,6 +534,7 @@ struct qcom_ethqos {
	bool ipa_enabled;
	/* Key Performance Indicators */
	bool print_kpi;

	unsigned int emac_phy_off_suspend;
	int loopback_speed;
	enum loopback_mode current_loopback;
@@ -527,6 +558,8 @@ struct qcom_ethqos {
	u32 cv2x_mode;
	struct ethqos_vlan_info cv2x_vlan;
	unsigned char cv2x_dev_addr[ETH_ALEN];

	struct ethqos_extra_dma_stats xstats;
};

struct pps_cfg {
+19 −0
Original line number Diff line number Diff line
@@ -460,6 +460,8 @@ static char * const IPA_OFFLOAD_EVENT_string[] = {
#define DMA_DSR0_RGRD(data) \
	((data) = readl_relaxed(DMA_DSR0_RGOFFADDR))

#define DMA_DSR1_RGOFFADDR ((BASE_ADDRESS + 0x1010))

#define DMA_CHRDR_RGOFFADDR (BASE_ADDRESS + 0x114c)

#define DMA_CHRDR_RGOFFADDRESS(i)\
@@ -503,6 +505,21 @@ static char * const IPA_OFFLOAD_EVENT_string[] = {
#define DMA_CHTDR_RGRD(i, data) \
		((data) = readl_relaxed(DMA_CHTDR_RGOFFADDRESS(i)))

#define DMA_CHTBAR_RGOFFADDR (BASE_ADDRESS + 0x1154)

#define DMA_CHTBAR_RGOFFADDRESS(i)\
			((DMA_CHTBAR_RGOFFADDR + ((i - 0) * 128)))

#define DMA_CHRBAR_RGOFFADDR (BASE_ADDRESS + 0x115c)

#define DMA_CHRBAR_RGOFFADDRESS(i)\
			((DMA_CHRBAR_RGOFFADDR + ((i - 0) * 128)))

#define DMA_CH_MISS_FRAME_CNT_RGOFFADDR (BASE_ADDRESS + 0x1164)

#define DMA_CH_MISS_FRAME_CNT_RGOFFADDRESS(i)\
			((DMA_CH_MISS_FRAME_CNT_RGOFFADDR + ((i - 0) * 128)))

#define DMA_TDTP_TPDR_RGOFFADDR (BASE_ADDRESS + 0x1120)

#define DMA_TDTP_TPDR_RGOFFADDRESS(i)\
@@ -554,6 +571,8 @@ static char * const IPA_OFFLOAD_EVENT_string[] = {
		data = ((data1 >> 13) & DMA_IER_CDEE_MASK);\
} while (0)

#define DMA_ISR_RGOFFADDR ((BASE_ADDRESS + 0x1008))

struct ethqos_tx_queue {
	struct stmmac_tx_queue *tx_q;
	unsigned int desc_cnt;