File Index
Files and directories
Sign in
FILE

health.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/intel/ice/devlink/health.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2024, Intel Corporation. */
  3
  4#include "ice.h"
  5#include "ice_adminq_cmd.h" /* for enum ice_aqc_health_status_elem */
  6#include "health.h"
  7
  8#define ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, obj, name) \
  9	devlink_fmsg_put(fmsg, #name, (obj)->name)
 10
 11#define ICE_HEALTH_STATUS_DATA_SIZE 2
 12
 13struct ice_health_status {
 14	enum ice_aqc_health_status code;
 15	const char *description;
 16	const char *solution;
 17	const char *data_label[ICE_HEALTH_STATUS_DATA_SIZE];
 18};
 19
 20/*
 21 * In addition to the health status codes provided below, the firmware might
 22 * generate Health Status Codes that are not pertinent to the end-user.
 23 * For instance, Health Code 0x1002 is triggered when the command fails.
 24 * Such codes should be disregarded by the end-user.
 25 * The below lookup requires to be sorted by code.
 26 */
 27
 28static const char ice_common_port_solutions[] =
 29	"Check your cable connection. Change or replace the module or cable. Manually set speed and duplex.";
 30static const char ice_port_number_label[] = "Port Number";
 31static const char ice_update_nvm_solution[] = "Update to the latest NVM image.";
 32
 33static const struct ice_health_status ice_health_status_lookup[] = {
 34	{ICE_AQC_HEALTH_STATUS_ERR_UNKNOWN_MOD_STRICT, "An unsupported module was detected.",
 35		ice_common_port_solutions, {ice_port_number_label}},
 36	{ICE_AQC_HEALTH_STATUS_ERR_MOD_TYPE, "Module type is not supported.",
 37		"Change or replace the module or cable.", {ice_port_number_label}},
 38	{ICE_AQC_HEALTH_STATUS_ERR_MOD_QUAL, "Module is not qualified.",
 39		ice_common_port_solutions, {ice_port_number_label}},
 40	{ICE_AQC_HEALTH_STATUS_ERR_MOD_COMM,
 41		"Device cannot communicate with the module.",
 42		"Check your cable connection. Change or replace the module or cable. Manually set speed and duplex.",
 43		{ice_port_number_label}},
 44	{ICE_AQC_HEALTH_STATUS_ERR_MOD_CONFLICT, "Unresolved module conflict.",
 45		"Manually set speed/duplex or change the port option. If the problem persists, use a cable/module that is found in the supported modules and cables list for this device.",
 46		{ice_port_number_label}},
 47	{ICE_AQC_HEALTH_STATUS_ERR_MOD_NOT_PRESENT, "Module is not present.",
 48		"Check that the module is inserted correctly. If the problem persists, use a cable/module that is found in the supported modules and cables list for this device.",
 49		{ice_port_number_label}},
 50	{ICE_AQC_HEALTH_STATUS_INFO_MOD_UNDERUTILIZED, "Underutilized module.",
 51		"Change or replace the module or cable. Change the port option.",
 52		{ice_port_number_label}},
 53	{ICE_AQC_HEALTH_STATUS_ERR_UNKNOWN_MOD_LENIENT, "An unsupported module was detected.",
 54		ice_common_port_solutions, {ice_port_number_label}},
 55	{ICE_AQC_HEALTH_STATUS_ERR_INVALID_LINK_CFG, "Invalid link configuration.",
 56		NULL, {ice_port_number_label}},
 57	{ICE_AQC_HEALTH_STATUS_ERR_PORT_ACCESS, "Port hardware access error.",
 58		ice_update_nvm_solution, {ice_port_number_label}},
 59	{ICE_AQC_HEALTH_STATUS_ERR_PORT_UNREACHABLE, "A port is unreachable.",
 60		"Change the port option. Update to the latest NVM image."},
 61	{ICE_AQC_HEALTH_STATUS_INFO_PORT_SPEED_MOD_LIMITED, "Port speed is limited due to module.",
 62		"Change the module or configure the port option to match the current module speed. Change the port option.",
 63		{ice_port_number_label}},
 64	{ICE_AQC_HEALTH_STATUS_ERR_PARALLEL_FAULT,
 65		"All configured link modes were attempted but failed to establish link. The device will restart the process to establish link.",
 66		"Check link partner connection and configuration.",
 67		{ice_port_number_label}},
 68	{ICE_AQC_HEALTH_STATUS_INFO_PORT_SPEED_PHY_LIMITED,
 69		"Port speed is limited by PHY capabilities.",
 70		"Change the module to align to port option.", {ice_port_number_label}},
 71	{ICE_AQC_HEALTH_STATUS_ERR_NETLIST_TOPO, "LOM topology netlist is corrupted.",
 72		ice_update_nvm_solution, {ice_port_number_label}},
 73	{ICE_AQC_HEALTH_STATUS_ERR_NETLIST, "Unrecoverable netlist error.",
 74		ice_update_nvm_solution, {ice_port_number_label}},
 75	{ICE_AQC_HEALTH_STATUS_ERR_TOPO_CONFLICT, "Port topology conflict.",
 76		"Change the port option. Update to the latest NVM image."},
 77	{ICE_AQC_HEALTH_STATUS_ERR_LINK_HW_ACCESS, "Unrecoverable hardware access error.",
 78		ice_update_nvm_solution, {ice_port_number_label}},
 79	{ICE_AQC_HEALTH_STATUS_ERR_LINK_RUNTIME, "Unrecoverable runtime error.",
 80		ice_update_nvm_solution, {ice_port_number_label}},
 81	{ICE_AQC_HEALTH_STATUS_ERR_DNL_INIT, "Link management engine failed to initialize.",
 82		ice_update_nvm_solution, {ice_port_number_label}},
 83	{ICE_AQC_HEALTH_STATUS_ERR_PHY_FW_LOAD,
 84		"Failed to load the firmware image in the external PHY.",
 85		ice_update_nvm_solution, {ice_port_number_label}},
 86	{ICE_AQC_HEALTH_STATUS_INFO_RECOVERY, "The device is in firmware recovery mode.",
 87		ice_update_nvm_solution, {"Extended Error"}},
 88	{ICE_AQC_HEALTH_STATUS_ERR_FLASH_ACCESS, "The flash chip cannot be accessed.",
 89		"If issue persists, call customer support.", {"Access Type"}},
 90	{ICE_AQC_HEALTH_STATUS_ERR_NVM_AUTH, "NVM authentication failed.",
 91		ice_update_nvm_solution},
 92	{ICE_AQC_HEALTH_STATUS_ERR_OROM_AUTH, "Option ROM authentication failed.",
 93		ice_update_nvm_solution},
 94	{ICE_AQC_HEALTH_STATUS_ERR_DDP_AUTH, "DDP package authentication failed.",
 95		"Update to latest base driver and DDP package."},
 96	{ICE_AQC_HEALTH_STATUS_ERR_NVM_COMPAT, "NVM image is incompatible.",
 97		ice_update_nvm_solution},
 98	{ICE_AQC_HEALTH_STATUS_ERR_OROM_COMPAT, "Option ROM is incompatible.",
 99		ice_update_nvm_solution, {"Expected PCI Device ID", "Expected Module ID"}},
100	{ICE_AQC_HEALTH_STATUS_ERR_DCB_MIB,
101		"Supplied MIB file is invalid. DCB reverted to default configuration.",
102		"Disable FW-LLDP and check DCBx system configuration.",
103		{ice_port_number_label, "MIB ID"}},
104};
105
106static int ice_health_status_lookup_compare(const void *a, const void *b)
107{
108	return ((struct ice_health_status *)a)->code - ((struct ice_health_status *)b)->code;
109}
110
111static const struct ice_health_status *ice_get_health_status(u16 code)
112{
113	struct ice_health_status key = { .code = code };
114
115	return bsearch(&key, ice_health_status_lookup, ARRAY_SIZE(ice_health_status_lookup),
116		       sizeof(struct ice_health_status), ice_health_status_lookup_compare);
117}
118
119static void ice_describe_status_code(struct devlink_fmsg *fmsg,
120				     struct ice_aqc_health_status_elem *hse)
121{
122	static const char *const aux_label[] = { "Aux Data 1", "Aux Data 2" };
123	const struct ice_health_status *health_code;
124	u32 internal_data[2];
125	u16 status_code;
126
127	status_code = le16_to_cpu(hse->health_status_code);
128
129	devlink_fmsg_put(fmsg, "Syndrome", status_code);
130	if (status_code) {
131		internal_data[0] = le32_to_cpu(hse->internal_data1);
132		internal_data[1] = le32_to_cpu(hse->internal_data2);
133
134		health_code = ice_get_health_status(status_code);
135		if (!health_code)
136			return;
137
138		devlink_fmsg_string_pair_put(fmsg, "Description", health_code->description);
139		if (health_code->solution)
140			devlink_fmsg_string_pair_put(fmsg, "Possible Solution",
141						     health_code->solution);
142
143		for (size_t i = 0; i < ICE_HEALTH_STATUS_DATA_SIZE; i++) {
144			if (internal_data[i] != ICE_AQC_HEALTH_STATUS_UNDEFINED_DATA)
145				devlink_fmsg_u32_pair_put(fmsg,
146							  health_code->data_label[i] ?
147							  health_code->data_label[i] :
148							  aux_label[i],
149							  internal_data[i]);
150		}
151	}
152}
153
154static int
155ice_port_reporter_diagnose(struct devlink_health_reporter *reporter, struct devlink_fmsg *fmsg,
156			   struct netlink_ext_ack *extack)
157{
158	struct ice_pf *pf = devlink_health_reporter_priv(reporter);
159
160	ice_describe_status_code(fmsg, &pf->health_reporters.port_status);
161	return 0;
162}
163
164static int
165ice_port_reporter_dump(struct devlink_health_reporter *reporter, struct devlink_fmsg *fmsg,
166		       void *priv_ctx, struct netlink_ext_ack __always_unused *extack)
167{
168	struct ice_pf *pf = devlink_health_reporter_priv(reporter);
169
170	ice_describe_status_code(fmsg, &pf->health_reporters.port_status);
171	return 0;
172}
173
174static int
175ice_fw_reporter_diagnose(struct devlink_health_reporter *reporter, struct devlink_fmsg *fmsg,
176			 struct netlink_ext_ack *extack)
177{
178	struct ice_pf *pf = devlink_health_reporter_priv(reporter);
179
180	ice_describe_status_code(fmsg, &pf->health_reporters.fw_status);
181	return 0;
182}
183
184static int
185ice_fw_reporter_dump(struct devlink_health_reporter *reporter, struct devlink_fmsg *fmsg,
186		     void *priv_ctx, struct netlink_ext_ack *extack)
187{
188	struct ice_pf *pf = devlink_health_reporter_priv(reporter);
189
190	ice_describe_status_code(fmsg, &pf->health_reporters.fw_status);
191	return 0;
192}
193
194static void ice_config_health_events(struct ice_pf *pf, bool enable)
195{
196	u8 enable_bits = 0;
197	int ret;
198
199	if (enable)
200		enable_bits = ICE_AQC_HEALTH_STATUS_SET_PF_SPECIFIC_MASK |
201			      ICE_AQC_HEALTH_STATUS_SET_GLOBAL_MASK;
202
203	ret = ice_aq_set_health_status_cfg(&pf->hw, enable_bits);
204	if (ret)
205		dev_err(ice_pf_to_dev(pf), "Failed to %s firmware health events, err %d aq_err %s\n",
206			str_enable_disable(enable), ret,
207			libie_aq_str(pf->hw.adminq.sq_last_status));
208}
209
210/**
211 * ice_process_health_status_event - Process the health status event from FW
212 * @pf: pointer to the PF structure
213 * @event: event structure containing the Health Status Event opcode
214 *
215 * Decode the Health Status Events and print the associated messages
216 */
217void ice_process_health_status_event(struct ice_pf *pf, struct ice_rq_event_info *event)
218{
219	const struct ice_aqc_health_status_elem *health_info;
220	const struct ice_aqc_get_health_status *cmd;
221	u16 count;
222
223	health_info = (struct ice_aqc_health_status_elem *)event->msg_buf;
224	cmd = libie_aq_raw(&event->desc);
225	count = le16_to_cpu(cmd->health_status_count);
226
227	if (count > (event->buf_len / sizeof(*health_info))) {
228		dev_err(ice_pf_to_dev(pf), "Received a health status event with invalid element count\n");
229		return;
230	}
231
232	for (size_t i = 0; i < count; i++) {
233		const struct ice_health_status *health_code;
234		u16 status_code;
235
236		status_code = le16_to_cpu(health_info->health_status_code);
237		health_code = ice_get_health_status(status_code);
238
239		if (health_code) {
240			switch (le16_to_cpu(health_info->event_source)) {
241			case ICE_AQC_HEALTH_STATUS_GLOBAL:
242				pf->health_reporters.fw_status = *health_info;
243				devlink_health_report(pf->health_reporters.fw,
244						      "FW syndrome reported", NULL);
245				break;
246			case ICE_AQC_HEALTH_STATUS_PF:
247			case ICE_AQC_HEALTH_STATUS_PORT:
248				pf->health_reporters.port_status = *health_info;
249				devlink_health_report(pf->health_reporters.port,
250						      "Port syndrome reported", NULL);
251				break;
252			default:
253				dev_err(ice_pf_to_dev(pf), "Health code with unknown source\n");
254			}
255		} else {
256			u32 data1, data2;
257			u16 source;
258
259			source = le16_to_cpu(health_info->event_source);
260			data1 = le32_to_cpu(health_info->internal_data1);
261			data2 = le32_to_cpu(health_info->internal_data2);
262			dev_dbg(ice_pf_to_dev(pf),
263				"Received internal health status code 0x%08x, source: 0x%08x, data1: 0x%08x, data2: 0x%08x",
264				status_code, source, data1, data2);
265		}
266		health_info++;
267	}
268}
269
270/**
271 * ice_devlink_health_report - boilerplate to call given @reporter
272 *
273 * @reporter: devlink health reporter to call, do nothing on NULL
274 * @msg: message to pass up, "event name" is fine
275 * @priv_ctx: typically some event struct
276 */
277static void ice_devlink_health_report(struct devlink_health_reporter *reporter,
278				      const char *msg, void *priv_ctx)
279{
280	if (!reporter)
281		return;
282
283	/* We do not do auto recovering, so return value of the below function
284	 * will always be 0, thus we do ignore it.
285	 */
286	devlink_health_report(reporter, msg, priv_ctx);
287}
288
289struct ice_mdd_event {
290	enum ice_mdd_src src;
291	u16 vf_num;
292	u16 queue;
293	u8 pf_num;
294	u8 event;
295};
296
297static const char *ice_mdd_src_to_str(enum ice_mdd_src src)
298{
299	switch (src) {
300	case ICE_MDD_SRC_TX_PQM:
301		return "tx_pqm";
302	case ICE_MDD_SRC_TX_TCLAN:
303		return "tx_tclan";
304	case ICE_MDD_SRC_TX_TDPU:
305		return "tx_tdpu";
306	case ICE_MDD_SRC_RX:
307		return "rx";
308	default:
309		return "invalid";
310	}
311}
312
313static int
314ice_mdd_reporter_dump(struct devlink_health_reporter *reporter,
315		      struct devlink_fmsg *fmsg, void *priv_ctx,
316		      struct netlink_ext_ack *extack)
317{
318	struct ice_mdd_event *mdd_event = priv_ctx;
319	const char *src;
320
321	if (!mdd_event)
322		return 0;
323
324	src = ice_mdd_src_to_str(mdd_event->src);
325
326	devlink_fmsg_obj_nest_start(fmsg);
327	devlink_fmsg_put(fmsg, "src", src);
328	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, pf_num);
329	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, vf_num);
330	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, event);
331	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, queue);
332	devlink_fmsg_obj_nest_end(fmsg);
333
334	return 0;
335}
336
337/**
338 * ice_report_mdd_event - Report an MDD event through devlink health
339 * @pf: the PF device structure
340 * @src: the HW block that was the source of this MDD event
341 * @pf_num: the pf_num on which the MDD event occurred
342 * @vf_num: the vf_num on which the MDD event occurred
343 * @event: the event type of the MDD event
344 * @queue: the queue on which the MDD event occurred
345 *
346 * Report an MDD event that has occurred on this PF.
347 */
348void ice_report_mdd_event(struct ice_pf *pf, enum ice_mdd_src src, u8 pf_num,
349			  u16 vf_num, u8 event, u16 queue)
350{
351	struct ice_mdd_event ev = {
352		.src = src,
353		.pf_num = pf_num,
354		.vf_num = vf_num,
355		.event = event,
356		.queue = queue,
357	};
358
359	ice_devlink_health_report(pf->health_reporters.mdd, "MDD event", &ev);
360}
361
362/**
363 * ice_fmsg_put_ptr - put hex value of pointer into fmsg
364 *
365 * @fmsg: devlink fmsg under construction
366 * @name: name to pass
367 * @ptr: 64 bit value to print as hex and put into fmsg
368 */
369static void ice_fmsg_put_ptr(struct devlink_fmsg *fmsg, const char *name,
370			     void *ptr)
371{
372	char buf[sizeof(ptr) * 3];
373
374	sprintf(buf, "%p", ptr);
375	devlink_fmsg_put(fmsg, name, buf);
376}
377
378struct ice_tx_hang_event {
379	u32 head;
380	u32 intr;
381	u16 vsi_num;
382	u16 queue;
383	u16 next_to_clean;
384	u16 next_to_use;
385	struct ice_tx_ring *tx_ring;
386};
387
388static int ice_tx_hang_reporter_dump(struct devlink_health_reporter *reporter,
389				     struct devlink_fmsg *fmsg, void *priv_ctx,
390				     struct netlink_ext_ack *extack)
391{
392	struct ice_tx_hang_event *event = priv_ctx;
393	struct sk_buff *skb;
394
395	if (!event)
396		return 0;
397
398	skb = event->tx_ring->tx_buf->skb;
399	devlink_fmsg_obj_nest_start(fmsg);
400	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, head);
401	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, intr);
402	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, vsi_num);
403	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, queue);
404	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, next_to_clean);
405	ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, next_to_use);
406	devlink_fmsg_put(fmsg, "irq-mapping", event->tx_ring->q_vector->name);
407	ice_fmsg_put_ptr(fmsg, "desc-ptr", event->tx_ring->desc);
408	ice_fmsg_put_ptr(fmsg, "dma-ptr", (void *)(long)event->tx_ring->dma);
409	ice_fmsg_put_ptr(fmsg, "skb-ptr", skb);
410	devlink_fmsg_binary_pair_put(fmsg, "desc", event->tx_ring->desc,
411				     event->tx_ring->count * sizeof(struct ice_tx_desc));
412	devlink_fmsg_dump_skb(fmsg, skb);
413	devlink_fmsg_obj_nest_end(fmsg);
414
415	return 0;
416}
417
418void ice_prep_tx_hang_report(struct ice_pf *pf, struct ice_tx_ring *tx_ring,
419			     u16 vsi_num, u32 head, u32 intr)
420{
421	struct ice_health_tx_hang_buf *buf = &pf->health_reporters.tx_hang_buf;
422
423	buf->tx_ring = tx_ring;
424	buf->vsi_num = vsi_num;
425	buf->head = head;
426	buf->intr = intr;
427}
428
429void ice_report_tx_hang(struct ice_pf *pf)
430{
431	struct ice_health_tx_hang_buf *buf = &pf->health_reporters.tx_hang_buf;
432	struct ice_tx_ring *tx_ring = buf->tx_ring;
433
434	struct ice_tx_hang_event ev = {
435		.head = buf->head,
436		.intr = buf->intr,
437		.vsi_num = buf->vsi_num,
438		.queue = tx_ring->q_index,
439		.next_to_clean = tx_ring->next_to_clean,
440		.next_to_use = tx_ring->next_to_use,
441		.tx_ring = tx_ring,
442	};
443
444	ice_devlink_health_report(pf->health_reporters.tx_hang, "Tx hang", &ev);
445}
446
447static struct devlink_health_reporter *
448ice_init_devlink_rep(struct ice_pf *pf,
449		     const struct devlink_health_reporter_ops *ops)
450{
451	struct devlink *devlink = priv_to_devlink(pf);
452	struct devlink_health_reporter *rep;
453
454	rep = devl_health_reporter_create(devlink, ops, pf);
455	if (IS_ERR(rep)) {
456		struct device *dev = ice_pf_to_dev(pf);
457
458		dev_err(dev, "failed to create devlink %s health report er",
459			ops->name);
460		return NULL;
461	}
462	return rep;
463}
464
465#define ICE_HEALTH_REPORTER_OPS_FIELD(_name, _field) \
466	._field = ice_##_name##_reporter_##_field,
467
468#define ICE_DEFINE_HEALTH_REPORTER_OPS_1(_name, _field1) \
469	static const struct devlink_health_reporter_ops ice_##_name##_reporter_ops = { \
470	.name = #_name, \
471	ICE_HEALTH_REPORTER_OPS_FIELD(_name, _field1) \
472	}
473
474#define ICE_DEFINE_HEALTH_REPORTER_OPS_2(_name, _field1, _field2) \
475	static const struct devlink_health_reporter_ops ice_##_name##_reporter_ops = { \
476	.name = #_name, \
477	ICE_HEALTH_REPORTER_OPS_FIELD(_name, _field1) \
478	ICE_HEALTH_REPORTER_OPS_FIELD(_name, _field2) \
479	}
480
481ICE_DEFINE_HEALTH_REPORTER_OPS_1(mdd, dump);
482ICE_DEFINE_HEALTH_REPORTER_OPS_1(tx_hang, dump);
483ICE_DEFINE_HEALTH_REPORTER_OPS_2(fw, dump, diagnose);
484ICE_DEFINE_HEALTH_REPORTER_OPS_2(port, dump, diagnose);
485
486/**
487 * ice_health_init - allocate and init all ice devlink health reporters and
488 * accompanied data
489 *
490 * @pf: PF struct
491 */
492void ice_health_init(struct ice_pf *pf)
493{
494	struct ice_health *reps = &pf->health_reporters;
495
496	reps->mdd = ice_init_devlink_rep(pf, &ice_mdd_reporter_ops);
497	reps->tx_hang = ice_init_devlink_rep(pf, &ice_tx_hang_reporter_ops);
498
499	if (ice_is_fw_health_report_supported(&pf->hw)) {
500		reps->fw = ice_init_devlink_rep(pf, &ice_fw_reporter_ops);
501		reps->port = ice_init_devlink_rep(pf, &ice_port_reporter_ops);
502		ice_config_health_events(pf, true);
503	}
504}
505
506/**
507 * ice_deinit_devl_reporter - destroy given devlink health reporter
508 * @reporter: reporter to destroy
509 */
510static void ice_deinit_devl_reporter(struct devlink_health_reporter *reporter)
511{
512	if (reporter)
513		devl_health_reporter_destroy(reporter);
514}
515
516/**
517 * ice_health_deinit - deallocate all ice devlink health reporters and
518 * accompanied data
519 *
520 * @pf: PF struct
521 */
522void ice_health_deinit(struct ice_pf *pf)
523{
524	ice_deinit_devl_reporter(pf->health_reporters.mdd);
525	ice_deinit_devl_reporter(pf->health_reporters.tx_hang);
526	if (ice_is_fw_health_report_supported(&pf->hw)) {
527		ice_deinit_devl_reporter(pf->health_reporters.fw);
528		ice_deinit_devl_reporter(pf->health_reporters.port);
529		ice_config_health_events(pf, false);
530	}
531}
532
533static
534void ice_health_assign_healthy_state(struct devlink_health_reporter *reporter)
535{
536	if (reporter)
537		devlink_health_reporter_state_update(reporter,
538						     DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
539}
540
541/**
542 * ice_health_clear - clear devlink health issues after a reset
543 * @pf: the PF device structure
544 *
545 * Mark the PF in healthy state again after a reset has completed.
546 */
547void ice_health_clear(struct ice_pf *pf)
548{
549	ice_health_assign_healthy_state(pf->health_reporters.mdd);
550	ice_health_assign_healthy_state(pf->health_reporters.tx_hang);
551}
~/ Read-only file preview.