Commit ba19a87b authored by Jijie Shao's avatar Jijie Shao Committed by Hao Chen
Browse files

net: hibmcge: Add support for abnormal irq handling feature

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IBU56J
CVE: NA

Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=fd394a334b1c



----------------------------------------------------------------------

the hardware error was reported by interrupt,
and need be fixed by doing function reset,
but the whole reset flow takes a long time,
should not do it in irq handler,
so do it in scheduled task.

Signed-off-by: default avatarJijie Shao <shaojijie@huawei.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarHao Chen <chenhao418@huawei.com>
parent a68cfd71
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ enum hbg_nic_state {
	HBG_NIC_STATE_EVENT_HANDLING = 0,
	HBG_NIC_STATE_RESETTING,
	HBG_NIC_STATE_RESET_FAIL,
	HBG_NIC_STATE_NEED_RESET, /* trigger a reset in scheduled task */
};

enum hbg_reset_type {
@@ -104,6 +105,7 @@ struct hbg_irq_info {
	u32 mask;
	bool re_enable;
	bool need_print;
	bool need_reset;
	u64 count;

	void (*irq_handle)(struct hbg_priv *priv, struct hbg_irq_info *info);
@@ -220,6 +222,7 @@ struct hbg_stats {
	u64 rx_fail_comma_cnt;

	u64 rx_dma_err_cnt;
	u64 rx_fifo_less_empty_thrsld_cnt;

	u64 tx_octets_total_ok_cnt;
	u64 tx_uc_pkt_cnt;
@@ -268,4 +271,6 @@ struct hbg_priv {
	struct delayed_work service_task;
};

void hbg_err_reset_task_schedule(struct hbg_priv *priv);

#endif
+4 −1
Original line number Diff line number Diff line
@@ -67,10 +67,11 @@ static int hbg_dbg_irq_info(struct seq_file *s, void *unused)
	for (i = 0; i < priv->vectors.info_array_len; i++) {
		info = &priv->vectors.info_array[i];
		seq_printf(s,
			   "%-20s: enabled: %-5s, logged: %-5s, count: %llu\n",
			   "%-20s: enabled: %-5s, reset: %-5s, logged: %-5s, count: %llu\n",
			   info->name,
			   str_true_false(hbg_hw_irq_is_enabled(priv,
								info->mask)),
			   str_true_false(info->need_reset),
			   str_true_false(info->need_print),
			   info->count);
	}
@@ -114,6 +115,8 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
		   state_str_true_false(priv, HBG_NIC_STATE_RESET_FAIL));
	seq_printf(s, "last reset type: %s\n",
		   reset_type_str[priv->reset_type]);
	seq_printf(s, "need reset state: %s\n",
		   state_str_true_false(priv, HBG_NIC_STATE_NEED_RESET));

	return 0;
}
+58 −0
Original line number Diff line number Diff line
@@ -105,6 +105,62 @@ int hbg_reset(struct hbg_priv *priv)
	return hbg_reset_done(priv, HBG_RESET_TYPE_FUNCTION);
}

void hbg_err_reset(struct hbg_priv *priv)
{
	bool running;

	rtnl_lock();
	running = netif_running(priv->netdev);
	if (running)
		dev_close(priv->netdev);

	hbg_reset(priv);

	/* in hbg_pci_err_detected(), we will detach first,
	 * so we need to attach before open
	 */
	if (!netif_device_present(priv->netdev))
		netif_device_attach(priv->netdev);

	if (running)
		dev_open(priv->netdev, NULL);
	rtnl_unlock();
}

static pci_ers_result_t hbg_pci_err_detected(struct pci_dev *pdev,
					     pci_channel_state_t state)
{
	struct net_device *netdev = pci_get_drvdata(pdev);

	netif_device_detach(netdev);

	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

	pci_disable_device(pdev);
	return PCI_ERS_RESULT_NEED_RESET;
}

static pci_ers_result_t hbg_pci_err_slot_reset(struct pci_dev *pdev)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct hbg_priv *priv = netdev_priv(netdev);

	if (pci_enable_device(pdev)) {
		dev_err(&pdev->dev,
			"failed to re-enable PCI device after reset\n");
		return PCI_ERS_RESULT_DISCONNECT;
	}

	pci_set_master(pdev);
	pci_restore_state(pdev);
	pci_save_state(pdev);

	hbg_err_reset(priv);
	netif_device_attach(netdev);
	return PCI_ERS_RESULT_RECOVERED;
}

static void hbg_pci_err_reset_prepare(struct pci_dev *pdev)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
@@ -124,6 +180,8 @@ static void hbg_pci_err_reset_done(struct pci_dev *pdev)
}

static const struct pci_error_handlers hbg_pci_err_handler = {
	.error_detected = hbg_pci_err_detected,
	.slot_reset = hbg_pci_err_slot_reset,
	.reset_prepare = hbg_pci_err_reset_prepare,
	.reset_done = hbg_pci_err_reset_done,
};
+1 −0
Original line number Diff line number Diff line
@@ -9,5 +9,6 @@
void hbg_set_pci_err_handler(struct pci_driver *pdrv);
int hbg_reset(struct hbg_priv *priv);
int hbg_rebuild(struct hbg_priv *priv);
void hbg_err_reset(struct hbg_priv *priv);

#endif
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ static const struct hbg_ethtool_stats hbg_ethtool_stats_info[] = {
			HBG_REG_RX_LENGTHFIELD_ERR_CNT_ADDR),
	HBG_STATS_REG_I(rx_fail_comma_cnt, HBG_REG_RX_FAIL_COMMA_CNT_ADDR),
	HBG_STATS_I(rx_dma_err_cnt),
	HBG_STATS_I(rx_fifo_less_empty_thrsld_cnt),

	HBG_STATS_REG_I(tx_uc_pkt_cnt, HBG_REG_TX_UC_PKTS_ADDR),
	HBG_STATS_REG_I(tx_vlan_pkt_cnt, HBG_REG_TX_TAGGED_ADDR),
Loading