Skip to content

Commit 44d4962

Browse files
committed
Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
Tony Nguyen says: ==================== ice: add support for devlink health events Przemek Kitszel says: Reports for two kinds of events are implemented, Malicious Driver Detection (MDD) and Tx hang. Patches 1, 2, 3: core improvements (checkpatch.pl, devlink extension) Patch 4: rename current ice devlink/ files Patches 5, 6, 7: ice devlink health infra + reporters Mateusz did good job caring for this series, and hardening the code. * '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue: ice: Add MDD logging via devlink health ice: add Tx hang devlink health reporter ice: rename devlink_port.[ch] to port.[ch] devlink: add devlink_fmsg_dump_skb() function devlink: add devlink_fmsg_put() macro checkpatch: don't complain on _Generic() use ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents a126061 + bc10274 commit 44d4962

File tree

14 files changed

+438
-12
lines changed

14 files changed

+438
-12
lines changed

drivers/net/ethernet/intel/ice/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ ice-y := ice_main.o \
3232
ice_parser_rt.o \
3333
ice_idc.o \
3434
devlink/devlink.o \
35-
devlink/devlink_port.o \
35+
devlink/health.o \
36+
devlink/port.o \
3637
ice_sf_eth.o \
3738
ice_sf_vsi_vlan_ops.o \
3839
ice_ddp.o \

drivers/net/ethernet/intel/ice/devlink/devlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "ice.h"
77
#include "ice_lib.h"
88
#include "devlink.h"
9-
#include "devlink_port.h"
9+
#include "port.h"
1010
#include "ice_eswitch.h"
1111
#include "ice_fw_update.h"
1212
#include "ice_dcb_lib.h"
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2024, Intel Corporation. */
3+
4+
#include "health.h"
5+
#include "ice.h"
6+
7+
#define ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, obj, name) \
8+
devlink_fmsg_put(fmsg, #name, (obj)->name)
9+
10+
/**
11+
* ice_devlink_health_report - boilerplate to call given @reporter
12+
*
13+
* @reporter: devlink health reporter to call, do nothing on NULL
14+
* @msg: message to pass up, "event name" is fine
15+
* @priv_ctx: typically some event struct
16+
*/
17+
static void ice_devlink_health_report(struct devlink_health_reporter *reporter,
18+
const char *msg, void *priv_ctx)
19+
{
20+
if (!reporter)
21+
return;
22+
23+
/* We do not do auto recovering, so return value of the below function
24+
* will always be 0, thus we do ignore it.
25+
*/
26+
devlink_health_report(reporter, msg, priv_ctx);
27+
}
28+
29+
struct ice_mdd_event {
30+
enum ice_mdd_src src;
31+
u16 vf_num;
32+
u16 queue;
33+
u8 pf_num;
34+
u8 event;
35+
};
36+
37+
static const char *ice_mdd_src_to_str(enum ice_mdd_src src)
38+
{
39+
switch (src) {
40+
case ICE_MDD_SRC_TX_PQM:
41+
return "tx_pqm";
42+
case ICE_MDD_SRC_TX_TCLAN:
43+
return "tx_tclan";
44+
case ICE_MDD_SRC_TX_TDPU:
45+
return "tx_tdpu";
46+
case ICE_MDD_SRC_RX:
47+
return "rx";
48+
default:
49+
return "invalid";
50+
}
51+
}
52+
53+
static int
54+
ice_mdd_reporter_dump(struct devlink_health_reporter *reporter,
55+
struct devlink_fmsg *fmsg, void *priv_ctx,
56+
struct netlink_ext_ack *extack)
57+
{
58+
struct ice_mdd_event *mdd_event = priv_ctx;
59+
const char *src;
60+
61+
if (!mdd_event)
62+
return 0;
63+
64+
src = ice_mdd_src_to_str(mdd_event->src);
65+
66+
devlink_fmsg_obj_nest_start(fmsg);
67+
devlink_fmsg_put(fmsg, "src", src);
68+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, pf_num);
69+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, vf_num);
70+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, event);
71+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, queue);
72+
devlink_fmsg_obj_nest_end(fmsg);
73+
74+
return 0;
75+
}
76+
77+
/**
78+
* ice_report_mdd_event - Report an MDD event through devlink health
79+
* @pf: the PF device structure
80+
* @src: the HW block that was the source of this MDD event
81+
* @pf_num: the pf_num on which the MDD event occurred
82+
* @vf_num: the vf_num on which the MDD event occurred
83+
* @event: the event type of the MDD event
84+
* @queue: the queue on which the MDD event occurred
85+
*
86+
* Report an MDD event that has occurred on this PF.
87+
*/
88+
void ice_report_mdd_event(struct ice_pf *pf, enum ice_mdd_src src, u8 pf_num,
89+
u16 vf_num, u8 event, u16 queue)
90+
{
91+
struct ice_mdd_event ev = {
92+
.src = src,
93+
.pf_num = pf_num,
94+
.vf_num = vf_num,
95+
.event = event,
96+
.queue = queue,
97+
};
98+
99+
ice_devlink_health_report(pf->health_reporters.mdd, "MDD event", &ev);
100+
}
101+
102+
/**
103+
* ice_fmsg_put_ptr - put hex value of pointer into fmsg
104+
*
105+
* @fmsg: devlink fmsg under construction
106+
* @name: name to pass
107+
* @ptr: 64 bit value to print as hex and put into fmsg
108+
*/
109+
static void ice_fmsg_put_ptr(struct devlink_fmsg *fmsg, const char *name,
110+
void *ptr)
111+
{
112+
char buf[sizeof(ptr) * 3];
113+
114+
sprintf(buf, "%p", ptr);
115+
devlink_fmsg_put(fmsg, name, buf);
116+
}
117+
118+
struct ice_tx_hang_event {
119+
u32 head;
120+
u32 intr;
121+
u16 vsi_num;
122+
u16 queue;
123+
u16 next_to_clean;
124+
u16 next_to_use;
125+
struct ice_tx_ring *tx_ring;
126+
};
127+
128+
static int ice_tx_hang_reporter_dump(struct devlink_health_reporter *reporter,
129+
struct devlink_fmsg *fmsg, void *priv_ctx,
130+
struct netlink_ext_ack *extack)
131+
{
132+
struct ice_tx_hang_event *event = priv_ctx;
133+
struct sk_buff *skb;
134+
135+
if (!event)
136+
return 0;
137+
138+
skb = event->tx_ring->tx_buf->skb;
139+
devlink_fmsg_obj_nest_start(fmsg);
140+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, head);
141+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, intr);
142+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, vsi_num);
143+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, queue);
144+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, next_to_clean);
145+
ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, next_to_use);
146+
devlink_fmsg_put(fmsg, "irq-mapping", event->tx_ring->q_vector->name);
147+
ice_fmsg_put_ptr(fmsg, "desc-ptr", event->tx_ring->desc);
148+
ice_fmsg_put_ptr(fmsg, "dma-ptr", (void *)(long)event->tx_ring->dma);
149+
ice_fmsg_put_ptr(fmsg, "skb-ptr", skb);
150+
devlink_fmsg_binary_pair_put(fmsg, "desc", event->tx_ring->desc,
151+
event->tx_ring->count * sizeof(struct ice_tx_desc));
152+
devlink_fmsg_dump_skb(fmsg, skb);
153+
devlink_fmsg_obj_nest_end(fmsg);
154+
155+
return 0;
156+
}
157+
158+
void ice_prep_tx_hang_report(struct ice_pf *pf, struct ice_tx_ring *tx_ring,
159+
u16 vsi_num, u32 head, u32 intr)
160+
{
161+
struct ice_health_tx_hang_buf *buf = &pf->health_reporters.tx_hang_buf;
162+
163+
buf->tx_ring = tx_ring;
164+
buf->vsi_num = vsi_num;
165+
buf->head = head;
166+
buf->intr = intr;
167+
}
168+
169+
void ice_report_tx_hang(struct ice_pf *pf)
170+
{
171+
struct ice_health_tx_hang_buf *buf = &pf->health_reporters.tx_hang_buf;
172+
struct ice_tx_ring *tx_ring = buf->tx_ring;
173+
174+
struct ice_tx_hang_event ev = {
175+
.head = buf->head,
176+
.intr = buf->intr,
177+
.vsi_num = buf->vsi_num,
178+
.queue = tx_ring->q_index,
179+
.next_to_clean = tx_ring->next_to_clean,
180+
.next_to_use = tx_ring->next_to_use,
181+
.tx_ring = tx_ring,
182+
};
183+
184+
ice_devlink_health_report(pf->health_reporters.tx_hang, "Tx hang", &ev);
185+
}
186+
187+
static struct devlink_health_reporter *
188+
ice_init_devlink_rep(struct ice_pf *pf,
189+
const struct devlink_health_reporter_ops *ops)
190+
{
191+
struct devlink *devlink = priv_to_devlink(pf);
192+
struct devlink_health_reporter *rep;
193+
const u64 graceful_period = 0;
194+
195+
rep = devl_health_reporter_create(devlink, ops, graceful_period, pf);
196+
if (IS_ERR(rep)) {
197+
struct device *dev = ice_pf_to_dev(pf);
198+
199+
dev_err(dev, "failed to create devlink %s health report er",
200+
ops->name);
201+
return NULL;
202+
}
203+
return rep;
204+
}
205+
206+
#define ICE_DEFINE_HEALTH_REPORTER_OPS(_name) \
207+
static const struct devlink_health_reporter_ops ice_ ## _name ## _reporter_ops = { \
208+
.name = #_name, \
209+
.dump = ice_ ## _name ## _reporter_dump, \
210+
}
211+
212+
ICE_DEFINE_HEALTH_REPORTER_OPS(mdd);
213+
ICE_DEFINE_HEALTH_REPORTER_OPS(tx_hang);
214+
215+
/**
216+
* ice_health_init - allocate and init all ice devlink health reporters and
217+
* accompanied data
218+
*
219+
* @pf: PF struct
220+
*/
221+
void ice_health_init(struct ice_pf *pf)
222+
{
223+
struct ice_health *reps = &pf->health_reporters;
224+
225+
reps->mdd = ice_init_devlink_rep(pf, &ice_mdd_reporter_ops);
226+
reps->tx_hang = ice_init_devlink_rep(pf, &ice_tx_hang_reporter_ops);
227+
}
228+
229+
/**
230+
* ice_deinit_devl_reporter - destroy given devlink health reporter
231+
* @reporter: reporter to destroy
232+
*/
233+
static void ice_deinit_devl_reporter(struct devlink_health_reporter *reporter)
234+
{
235+
if (reporter)
236+
devl_health_reporter_destroy(reporter);
237+
}
238+
239+
/**
240+
* ice_health_deinit - deallocate all ice devlink health reporters and
241+
* accompanied data
242+
*
243+
* @pf: PF struct
244+
*/
245+
void ice_health_deinit(struct ice_pf *pf)
246+
{
247+
ice_deinit_devl_reporter(pf->health_reporters.mdd);
248+
ice_deinit_devl_reporter(pf->health_reporters.tx_hang);
249+
}
250+
251+
static
252+
void ice_health_assign_healthy_state(struct devlink_health_reporter *reporter)
253+
{
254+
if (reporter)
255+
devlink_health_reporter_state_update(reporter,
256+
DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
257+
}
258+
259+
/**
260+
* ice_health_clear - clear devlink health issues after a reset
261+
* @pf: the PF device structure
262+
*
263+
* Mark the PF in healthy state again after a reset has completed.
264+
*/
265+
void ice_health_clear(struct ice_pf *pf)
266+
{
267+
ice_health_assign_healthy_state(pf->health_reporters.mdd);
268+
ice_health_assign_healthy_state(pf->health_reporters.tx_hang);
269+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2024, Intel Corporation. */
3+
4+
#ifndef _HEALTH_H_
5+
#define _HEALTH_H_
6+
7+
#include <linux/types.h>
8+
9+
/**
10+
* DOC: health.h
11+
*
12+
* This header file stores everything that is needed for broadly understood
13+
* devlink health mechanism for ice driver.
14+
*/
15+
16+
struct ice_pf;
17+
struct ice_tx_ring;
18+
19+
enum ice_mdd_src {
20+
ICE_MDD_SRC_TX_PQM,
21+
ICE_MDD_SRC_TX_TCLAN,
22+
ICE_MDD_SRC_TX_TDPU,
23+
ICE_MDD_SRC_RX,
24+
};
25+
26+
/**
27+
* struct ice_health - stores ice devlink health reporters and accompanied data
28+
* @tx_hang: devlink health reporter for tx_hang event
29+
* @mdd: devlink health reporter for MDD detection event
30+
* @tx_hang_buf: pre-allocated place to put info for Tx hang reporter from
31+
* non-sleeping context
32+
* @tx_ring: ring that the hang occurred on
33+
* @head: descriptor head
34+
* @intr: interrupt register value
35+
* @vsi_num: VSI owning the queue that the hang occurred on
36+
*/
37+
struct ice_health {
38+
struct devlink_health_reporter *mdd;
39+
struct devlink_health_reporter *tx_hang;
40+
struct_group_tagged(ice_health_tx_hang_buf, tx_hang_buf,
41+
struct ice_tx_ring *tx_ring;
42+
u32 head;
43+
u32 intr;
44+
u16 vsi_num;
45+
);
46+
};
47+
48+
void ice_health_init(struct ice_pf *pf);
49+
void ice_health_deinit(struct ice_pf *pf);
50+
void ice_health_clear(struct ice_pf *pf);
51+
52+
void ice_prep_tx_hang_report(struct ice_pf *pf, struct ice_tx_ring *tx_ring,
53+
u16 vsi_num, u32 head, u32 intr);
54+
void ice_report_mdd_event(struct ice_pf *pf, enum ice_mdd_src src, u8 pf_num,
55+
u16 vf_num, u8 event, u16 queue);
56+
void ice_report_tx_hang(struct ice_pf *pf);
57+
58+
#endif /* _HEALTH_H_ */

drivers/net/ethernet/intel/ice/devlink/devlink_port.c renamed to drivers/net/ethernet/intel/ice/devlink/port.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#include "ice.h"
77
#include "devlink.h"
8-
#include "devlink_port.h"
8+
#include "port.h"
99
#include "ice_lib.h"
1010
#include "ice_fltr.h"
1111

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#include "ice_irq.h"
7979
#include "ice_dpll.h"
8080
#include "ice_adapter.h"
81+
#include "devlink/health.h"
8182

8283
#define ICE_BAR0 0
8384
#define ICE_REQ_DESC_MULTIPLE 32
@@ -665,6 +666,7 @@ struct ice_pf {
665666
struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES];
666667
struct ice_dplls dplls;
667668
struct device *hwmon_dev;
669+
struct ice_health health_reporters;
668670

669671
u8 num_quanta_prof_used;
670672
};

drivers/net/ethernet/intel/ice/ice_eswitch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#define _ICE_ESWITCH_H_
66

77
#include <net/devlink.h>
8-
#include "devlink/devlink_port.h"
8+
#include "devlink/port.h"
99

1010
#ifdef CONFIG_ICE_SWITCHDEV
1111
void ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf);

0 commit comments

Comments
 (0)