xref: /linux/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c (revision 0ad9617c78acbc71373fb341a6f75d4012b01d69)
1*3f5a61f6SJijie Shao // SPDX-License-Identifier: GPL-2.0+
2*3f5a61f6SJijie Shao // Copyright (c) 2024 Hisilicon Limited.
3*3f5a61f6SJijie Shao 
4*3f5a61f6SJijie Shao #include <linux/etherdevice.h>
5*3f5a61f6SJijie Shao #include <linux/netdevice.h>
6*3f5a61f6SJijie Shao #include <linux/phy.h>
7*3f5a61f6SJijie Shao #include <linux/rtnetlink.h>
8*3f5a61f6SJijie Shao #include "hbg_common.h"
9*3f5a61f6SJijie Shao #include "hbg_err.h"
10*3f5a61f6SJijie Shao #include "hbg_hw.h"
11*3f5a61f6SJijie Shao 
12*3f5a61f6SJijie Shao static void hbg_restore_mac_table(struct hbg_priv *priv)
13*3f5a61f6SJijie Shao {
14*3f5a61f6SJijie Shao 	struct hbg_mac_filter *filter = &priv->filter;
15*3f5a61f6SJijie Shao 	u64 addr;
16*3f5a61f6SJijie Shao 	u32 i;
17*3f5a61f6SJijie Shao 
18*3f5a61f6SJijie Shao 	for (i = 0; i < filter->table_max_len; i++)
19*3f5a61f6SJijie Shao 		if (!is_zero_ether_addr(filter->mac_table[i].addr)) {
20*3f5a61f6SJijie Shao 			addr = ether_addr_to_u64(filter->mac_table[i].addr);
21*3f5a61f6SJijie Shao 			hbg_hw_set_uc_addr(priv, addr, i);
22*3f5a61f6SJijie Shao 		}
23*3f5a61f6SJijie Shao 
24*3f5a61f6SJijie Shao 	hbg_hw_set_mac_filter_enable(priv, priv->filter.enabled);
25*3f5a61f6SJijie Shao }
26*3f5a61f6SJijie Shao 
27*3f5a61f6SJijie Shao static void hbg_restore_user_def_settings(struct hbg_priv *priv)
28*3f5a61f6SJijie Shao {
29*3f5a61f6SJijie Shao 	struct ethtool_pauseparam *pause_param = &priv->user_def.pause_param;
30*3f5a61f6SJijie Shao 
31*3f5a61f6SJijie Shao 	hbg_restore_mac_table(priv);
32*3f5a61f6SJijie Shao 	hbg_hw_set_mtu(priv, priv->netdev->mtu);
33*3f5a61f6SJijie Shao 	hbg_hw_set_pause_enable(priv, pause_param->tx_pause,
34*3f5a61f6SJijie Shao 				pause_param->rx_pause);
35*3f5a61f6SJijie Shao }
36*3f5a61f6SJijie Shao 
37*3f5a61f6SJijie Shao int hbg_rebuild(struct hbg_priv *priv)
38*3f5a61f6SJijie Shao {
39*3f5a61f6SJijie Shao 	int ret;
40*3f5a61f6SJijie Shao 
41*3f5a61f6SJijie Shao 	ret = hbg_hw_init(priv);
42*3f5a61f6SJijie Shao 	if (ret)
43*3f5a61f6SJijie Shao 		return ret;
44*3f5a61f6SJijie Shao 
45*3f5a61f6SJijie Shao 	hbg_restore_user_def_settings(priv);
46*3f5a61f6SJijie Shao 	return 0;
47*3f5a61f6SJijie Shao }
48*3f5a61f6SJijie Shao 
49*3f5a61f6SJijie Shao static int hbg_reset_prepare(struct hbg_priv *priv, enum hbg_reset_type type)
50*3f5a61f6SJijie Shao {
51*3f5a61f6SJijie Shao 	int ret;
52*3f5a61f6SJijie Shao 
53*3f5a61f6SJijie Shao 	ASSERT_RTNL();
54*3f5a61f6SJijie Shao 
55*3f5a61f6SJijie Shao 	if (netif_running(priv->netdev)) {
56*3f5a61f6SJijie Shao 		dev_warn(&priv->pdev->dev,
57*3f5a61f6SJijie Shao 			 "failed to reset because port is up\n");
58*3f5a61f6SJijie Shao 		return -EBUSY;
59*3f5a61f6SJijie Shao 	}
60*3f5a61f6SJijie Shao 
61*3f5a61f6SJijie Shao 	priv->reset_type = type;
62*3f5a61f6SJijie Shao 	set_bit(HBG_NIC_STATE_RESETTING, &priv->state);
63*3f5a61f6SJijie Shao 	clear_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state);
64*3f5a61f6SJijie Shao 	ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_RESET);
65*3f5a61f6SJijie Shao 	if (ret) {
66*3f5a61f6SJijie Shao 		set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state);
67*3f5a61f6SJijie Shao 		clear_bit(HBG_NIC_STATE_RESETTING, &priv->state);
68*3f5a61f6SJijie Shao 	}
69*3f5a61f6SJijie Shao 
70*3f5a61f6SJijie Shao 	return ret;
71*3f5a61f6SJijie Shao }
72*3f5a61f6SJijie Shao 
73*3f5a61f6SJijie Shao static int hbg_reset_done(struct hbg_priv *priv, enum hbg_reset_type type)
74*3f5a61f6SJijie Shao {
75*3f5a61f6SJijie Shao 	int ret;
76*3f5a61f6SJijie Shao 
77*3f5a61f6SJijie Shao 	if (!test_bit(HBG_NIC_STATE_RESETTING, &priv->state) ||
78*3f5a61f6SJijie Shao 	    type != priv->reset_type)
79*3f5a61f6SJijie Shao 		return 0;
80*3f5a61f6SJijie Shao 
81*3f5a61f6SJijie Shao 	ASSERT_RTNL();
82*3f5a61f6SJijie Shao 
83*3f5a61f6SJijie Shao 	clear_bit(HBG_NIC_STATE_RESETTING, &priv->state);
84*3f5a61f6SJijie Shao 	ret = hbg_rebuild(priv);
85*3f5a61f6SJijie Shao 	if (ret) {
86*3f5a61f6SJijie Shao 		set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state);
87*3f5a61f6SJijie Shao 		dev_err(&priv->pdev->dev, "failed to rebuild after reset\n");
88*3f5a61f6SJijie Shao 		return ret;
89*3f5a61f6SJijie Shao 	}
90*3f5a61f6SJijie Shao 
91*3f5a61f6SJijie Shao 	dev_info(&priv->pdev->dev, "reset done\n");
92*3f5a61f6SJijie Shao 	return ret;
93*3f5a61f6SJijie Shao }
94*3f5a61f6SJijie Shao 
95*3f5a61f6SJijie Shao /* must be protected by rtnl lock */
96*3f5a61f6SJijie Shao int hbg_reset(struct hbg_priv *priv)
97*3f5a61f6SJijie Shao {
98*3f5a61f6SJijie Shao 	int ret;
99*3f5a61f6SJijie Shao 
100*3f5a61f6SJijie Shao 	ASSERT_RTNL();
101*3f5a61f6SJijie Shao 	ret = hbg_reset_prepare(priv, HBG_RESET_TYPE_FUNCTION);
102*3f5a61f6SJijie Shao 	if (ret)
103*3f5a61f6SJijie Shao 		return ret;
104*3f5a61f6SJijie Shao 
105*3f5a61f6SJijie Shao 	return hbg_reset_done(priv, HBG_RESET_TYPE_FUNCTION);
106*3f5a61f6SJijie Shao }
107*3f5a61f6SJijie Shao 
108*3f5a61f6SJijie Shao static void hbg_pci_err_reset_prepare(struct pci_dev *pdev)
109*3f5a61f6SJijie Shao {
110*3f5a61f6SJijie Shao 	struct net_device *netdev = pci_get_drvdata(pdev);
111*3f5a61f6SJijie Shao 	struct hbg_priv *priv = netdev_priv(netdev);
112*3f5a61f6SJijie Shao 
113*3f5a61f6SJijie Shao 	rtnl_lock();
114*3f5a61f6SJijie Shao 	hbg_reset_prepare(priv, HBG_RESET_TYPE_FLR);
115*3f5a61f6SJijie Shao }
116*3f5a61f6SJijie Shao 
117*3f5a61f6SJijie Shao static void hbg_pci_err_reset_done(struct pci_dev *pdev)
118*3f5a61f6SJijie Shao {
119*3f5a61f6SJijie Shao 	struct net_device *netdev = pci_get_drvdata(pdev);
120*3f5a61f6SJijie Shao 	struct hbg_priv *priv = netdev_priv(netdev);
121*3f5a61f6SJijie Shao 
122*3f5a61f6SJijie Shao 	hbg_reset_done(priv, HBG_RESET_TYPE_FLR);
123*3f5a61f6SJijie Shao 	rtnl_unlock();
124*3f5a61f6SJijie Shao }
125*3f5a61f6SJijie Shao 
126*3f5a61f6SJijie Shao static const struct pci_error_handlers hbg_pci_err_handler = {
127*3f5a61f6SJijie Shao 	.reset_prepare = hbg_pci_err_reset_prepare,
128*3f5a61f6SJijie Shao 	.reset_done = hbg_pci_err_reset_done,
129*3f5a61f6SJijie Shao };
130*3f5a61f6SJijie Shao 
131*3f5a61f6SJijie Shao void hbg_set_pci_err_handler(struct pci_driver *pdrv)
132*3f5a61f6SJijie Shao {
133*3f5a61f6SJijie Shao 	pdrv->err_handler = &hbg_pci_err_handler;
134*3f5a61f6SJijie Shao }
135