Skip to content

Commit fd394a3

Browse files
Jijie ShaoPaolo Abeni
authored andcommitted
net: hibmcge: Add support for abnormal irq handling feature
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: Jijie Shao <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 833b65a commit fd394a3

File tree

8 files changed

+112
-23
lines changed

8 files changed

+112
-23
lines changed

drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ enum hbg_nic_state {
3636
HBG_NIC_STATE_EVENT_HANDLING = 0,
3737
HBG_NIC_STATE_RESETTING,
3838
HBG_NIC_STATE_RESET_FAIL,
39+
HBG_NIC_STATE_NEED_RESET, /* trigger a reset in scheduled task */
3940
};
4041

4142
enum hbg_reset_type {
@@ -104,6 +105,7 @@ struct hbg_irq_info {
104105
u32 mask;
105106
bool re_enable;
106107
bool need_print;
108+
bool need_reset;
107109
u64 count;
108110

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

222224
u64 rx_dma_err_cnt;
225+
u64 rx_fifo_less_empty_thrsld_cnt;
223226

224227
u64 tx_octets_total_ok_cnt;
225228
u64 tx_uc_pkt_cnt;
@@ -268,4 +271,6 @@ struct hbg_priv {
268271
struct delayed_work service_task;
269272
};
270273

274+
void hbg_err_reset_task_schedule(struct hbg_priv *priv);
275+
271276
#endif

drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ static int hbg_dbg_irq_info(struct seq_file *s, void *unused)
6767
for (i = 0; i < priv->vectors.info_array_len; i++) {
6868
info = &priv->vectors.info_array[i];
6969
seq_printf(s,
70-
"%-20s: enabled: %-5s, logged: %-5s, count: %llu\n",
70+
"%-20s: enabled: %-5s, reset: %-5s, logged: %-5s, count: %llu\n",
7171
info->name,
7272
str_true_false(hbg_hw_irq_is_enabled(priv,
7373
info->mask)),
74+
str_true_false(info->need_reset),
7475
str_true_false(info->need_print),
7576
info->count);
7677
}
@@ -114,6 +115,8 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
114115
state_str_true_false(priv, HBG_NIC_STATE_RESET_FAIL));
115116
seq_printf(s, "last reset type: %s\n",
116117
reset_type_str[priv->reset_type]);
118+
seq_printf(s, "need reset state: %s\n",
119+
state_str_true_false(priv, HBG_NIC_STATE_NEED_RESET));
117120

118121
return 0;
119122
}

drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,62 @@ int hbg_reset(struct hbg_priv *priv)
105105
return hbg_reset_done(priv, HBG_RESET_TYPE_FUNCTION);
106106
}
107107

108+
void hbg_err_reset(struct hbg_priv *priv)
109+
{
110+
bool running;
111+
112+
rtnl_lock();
113+
running = netif_running(priv->netdev);
114+
if (running)
115+
dev_close(priv->netdev);
116+
117+
hbg_reset(priv);
118+
119+
/* in hbg_pci_err_detected(), we will detach first,
120+
* so we need to attach before open
121+
*/
122+
if (!netif_device_present(priv->netdev))
123+
netif_device_attach(priv->netdev);
124+
125+
if (running)
126+
dev_open(priv->netdev, NULL);
127+
rtnl_unlock();
128+
}
129+
130+
static pci_ers_result_t hbg_pci_err_detected(struct pci_dev *pdev,
131+
pci_channel_state_t state)
132+
{
133+
struct net_device *netdev = pci_get_drvdata(pdev);
134+
135+
netif_device_detach(netdev);
136+
137+
if (state == pci_channel_io_perm_failure)
138+
return PCI_ERS_RESULT_DISCONNECT;
139+
140+
pci_disable_device(pdev);
141+
return PCI_ERS_RESULT_NEED_RESET;
142+
}
143+
144+
static pci_ers_result_t hbg_pci_err_slot_reset(struct pci_dev *pdev)
145+
{
146+
struct net_device *netdev = pci_get_drvdata(pdev);
147+
struct hbg_priv *priv = netdev_priv(netdev);
148+
149+
if (pci_enable_device(pdev)) {
150+
dev_err(&pdev->dev,
151+
"failed to re-enable PCI device after reset\n");
152+
return PCI_ERS_RESULT_DISCONNECT;
153+
}
154+
155+
pci_set_master(pdev);
156+
pci_restore_state(pdev);
157+
pci_save_state(pdev);
158+
159+
hbg_err_reset(priv);
160+
netif_device_attach(netdev);
161+
return PCI_ERS_RESULT_RECOVERED;
162+
}
163+
108164
static void hbg_pci_err_reset_prepare(struct pci_dev *pdev)
109165
{
110166
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -124,6 +180,8 @@ static void hbg_pci_err_reset_done(struct pci_dev *pdev)
124180
}
125181

126182
static const struct pci_error_handlers hbg_pci_err_handler = {
183+
.error_detected = hbg_pci_err_detected,
184+
.slot_reset = hbg_pci_err_slot_reset,
127185
.reset_prepare = hbg_pci_err_reset_prepare,
128186
.reset_done = hbg_pci_err_reset_done,
129187
};

drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
void hbg_set_pci_err_handler(struct pci_driver *pdrv);
1010
int hbg_reset(struct hbg_priv *priv);
1111
int hbg_rebuild(struct hbg_priv *priv);
12+
void hbg_err_reset(struct hbg_priv *priv);
1213

1314
#endif

drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ static const struct hbg_ethtool_stats hbg_ethtool_stats_info[] = {
6969
HBG_REG_RX_LENGTHFIELD_ERR_CNT_ADDR),
7070
HBG_STATS_REG_I(rx_fail_comma_cnt, HBG_REG_RX_FAIL_COMMA_CNT_ADDR),
7171
HBG_STATS_I(rx_dma_err_cnt),
72+
HBG_STATS_I(rx_fifo_less_empty_thrsld_cnt),
7273

7374
HBG_STATS_REG_I(tx_uc_pkt_cnt, HBG_REG_TX_UC_PKTS_ADDR),
7475
HBG_STATS_REG_I(tx_vlan_pkt_cnt, HBG_REG_TX_TAGGED_ADDR),

drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ static void hbg_irq_handle_err(struct hbg_priv *priv,
1111
if (irq_info->need_print)
1212
dev_err(&priv->pdev->dev,
1313
"receive error interrupt: %s\n", irq_info->name);
14+
15+
if (irq_info->need_reset)
16+
hbg_err_reset_task_schedule(priv);
1417
}
1518

1619
static void hbg_irq_handle_tx(struct hbg_priv *priv,
@@ -25,30 +28,38 @@ static void hbg_irq_handle_rx(struct hbg_priv *priv,
2528
napi_schedule(&priv->rx_ring.napi);
2629
}
2730

28-
#define HBG_TXRX_IRQ_I(name, handle) \
29-
{#name, HBG_INT_MSK_##name##_B, false, false, 0, handle}
30-
#define HBG_ERR_IRQ_I(name, need_print) \
31-
{#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err}
31+
static void hbg_irq_handle_rx_buf_val(struct hbg_priv *priv,
32+
struct hbg_irq_info *irq_info)
33+
{
34+
priv->stats.rx_fifo_less_empty_thrsld_cnt++;
35+
}
36+
37+
#define HBG_IRQ_I(name, handle) \
38+
{#name, HBG_INT_MSK_##name##_B, false, false, false, 0, handle}
39+
#define HBG_ERR_IRQ_I(name, need_print, ndde_reset) \
40+
{#name, HBG_INT_MSK_##name##_B, true, need_print, \
41+
ndde_reset, 0, hbg_irq_handle_err}
3242

3343
static struct hbg_irq_info hbg_irqs[] = {
34-
HBG_TXRX_IRQ_I(RX, hbg_irq_handle_rx),
35-
HBG_TXRX_IRQ_I(TX, hbg_irq_handle_tx),
36-
HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true),
37-
HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true),
38-
HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true),
39-
HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true),
40-
HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true),
41-
HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true),
42-
HBG_ERR_IRQ_I(TX_AHB_ERR, true),
43-
HBG_ERR_IRQ_I(RX_BUF_AVL, false),
44-
HBG_ERR_IRQ_I(REL_BUF_ERR, true),
45-
HBG_ERR_IRQ_I(TXCFG_AVL, false),
46-
HBG_ERR_IRQ_I(TX_DROP, false),
47-
HBG_ERR_IRQ_I(RX_DROP, false),
48-
HBG_ERR_IRQ_I(RX_AHB_ERR, true),
49-
HBG_ERR_IRQ_I(MAC_FIFO_ERR, false),
50-
HBG_ERR_IRQ_I(RBREQ_ERR, false),
51-
HBG_ERR_IRQ_I(WE_ERR, false),
44+
HBG_IRQ_I(RX, hbg_irq_handle_rx),
45+
HBG_IRQ_I(TX, hbg_irq_handle_tx),
46+
HBG_ERR_IRQ_I(TX_PKT_CPL, true, true),
47+
HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true, true),
48+
HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true, true),
49+
HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true, true),
50+
HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true, true),
51+
HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true, true),
52+
HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true, false),
53+
HBG_ERR_IRQ_I(TX_AHB_ERR, true, true),
54+
HBG_IRQ_I(RX_BUF_AVL, hbg_irq_handle_rx_buf_val),
55+
HBG_ERR_IRQ_I(REL_BUF_ERR, true, false),
56+
HBG_ERR_IRQ_I(TXCFG_AVL, false, false),
57+
HBG_ERR_IRQ_I(TX_DROP, false, false),
58+
HBG_ERR_IRQ_I(RX_DROP, false, false),
59+
HBG_ERR_IRQ_I(RX_AHB_ERR, true, false),
60+
HBG_ERR_IRQ_I(MAC_FIFO_ERR, true, true),
61+
HBG_ERR_IRQ_I(RBREQ_ERR, true, true),
62+
HBG_ERR_IRQ_I(WE_ERR, true, true),
5263
};
5364

5465
static irqreturn_t hbg_irq_handle(int irq_num, void *p)

drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ static void hbg_service_task(struct work_struct *work)
283283
struct hbg_priv *priv = container_of(work, struct hbg_priv,
284284
service_task.work);
285285

286+
if (test_and_clear_bit(HBG_NIC_STATE_NEED_RESET, &priv->state))
287+
hbg_err_reset(priv);
288+
286289
/* The type of statistics register is u32,
287290
* To prevent the statistics register from overflowing,
288291
* the driver dumps the statistics every 30 seconds.
@@ -292,6 +295,12 @@ static void hbg_service_task(struct work_struct *work)
292295
msecs_to_jiffies(30 * MSEC_PER_SEC));
293296
}
294297

298+
void hbg_err_reset_task_schedule(struct hbg_priv *priv)
299+
{
300+
set_bit(HBG_NIC_STATE_NEED_RESET, &priv->state);
301+
schedule_delayed_work(&priv->service_task, 0);
302+
}
303+
295304
static void hbg_cancel_delayed_work_sync(void *data)
296305
{
297306
cancel_delayed_work_sync(data);

drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
#define HBG_INT_MSK_MAC_PCS_TX_FIFO_ERR_B BIT(17)
149149
#define HBG_INT_MSK_MAC_PCS_RX_FIFO_ERR_B BIT(16)
150150
#define HBG_INT_MSK_MAC_MII_FIFO_ERR_B BIT(15)
151+
#define HBG_INT_MSK_TX_PKT_CPL_B BIT(14)
151152
#define HBG_INT_MSK_TX_B BIT(1) /* just used in driver */
152153
#define HBG_INT_MSK_RX_B BIT(0) /* just used in driver */
153154
#define HBG_REG_CF_INTRPT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0434)

0 commit comments

Comments
 (0)