Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pds_core: add devlink health facilities

Add devlink health reporting on top of our fw watchdog.

Example:
# devlink health show pci/0000:2b:00.0 reporter fw
pci/0000:2b:00.0:
reporter fw
state healthy error 0 recover 0
# devlink health diagnose pci/0000:2b:00.0 reporter fw
Status: healthy State: 1 Generation: 0 Recoveries: 0

Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Shannon Nelson and committed by
David S. Miller
25b450c0 c2dbb090

+88 -1
+12
Documentation/networking/device_drivers/ethernet/amd/pds_core.rst
··· 26 26 pds_core 0000:b6:00.0: 252.048 Gb/s available PCIe bandwidth (16.0 GT/s PCIe x16 link) 27 27 pds_core 0000:b6:00.0: FW: 1.60.0-73 28 28 29 + Health Reporters 30 + ================ 31 + 32 + The driver supports a devlink health reporter for FW status:: 33 + 34 + # devlink health show pci/0000:2b:00.0 reporter fw 35 + pci/0000:2b:00.0: 36 + reporter fw 37 + state healthy error 0 recover 0 38 + # devlink health diagnose pci/0000:2b:00.0 reporter fw 39 + Status: healthy State: 1 Generation: 0 Recoveries: 0 40 + 29 41 Support 30 42 ======= 31 43
+1
drivers/net/ethernet/amd/pds_core/Makefile
··· 4 4 obj-$(CONFIG_PDS_CORE) := pds_core.o 5 5 6 6 pds_core-y := main.o \ 7 + devlink.o \ 7 8 dev.o \ 8 9 core.o 9 10
+7 -1
drivers/net/ethernet/amd/pds_core/core.c
··· 5 5 6 6 int pdsc_setup(struct pdsc *pdsc, bool init) 7 7 { 8 - int err = 0; 8 + int err; 9 9 10 10 if (init) 11 11 err = pdsc_dev_init(pdsc); ··· 42 42 return; 43 43 } 44 44 45 + devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); 46 + 45 47 pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY); 46 48 } 47 49 ··· 59 57 err = pdsc_setup(pdsc, PDSC_SETUP_RECOVERY); 60 58 if (err) 61 59 goto err_out; 60 + 61 + pdsc->fw_recoveries++; 62 + devlink_health_reporter_state_update(pdsc->fw_reporter, 63 + DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); 62 64 63 65 return; 64 66
+6
drivers/net/ethernet/amd/pds_core/core.h
··· 68 68 struct timer_list wdtimer; 69 69 unsigned int wdtimer_period; 70 70 struct work_struct health_work; 71 + struct devlink_health_reporter *fw_reporter; 72 + u32 fw_recoveries; 71 73 72 74 struct pdsc_devinfo dev_info; 73 75 struct pds_core_dev_identity dev_ident; ··· 89 87 dma_addr_t phy_db_pages; 90 88 u64 __iomem *kern_dbpage; 91 89 }; 90 + 91 + int pdsc_fw_reporter_diagnose(struct devlink_health_reporter *reporter, 92 + struct devlink_fmsg *fmsg, 93 + struct netlink_ext_ack *extack); 92 94 93 95 void pdsc_debugfs_create(void); 94 96 void pdsc_debugfs_destroy(void);
+40
drivers/net/ethernet/amd/pds_core/devlink.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2023 Advanced Micro Devices, Inc */ 3 + 4 + #include "core.h" 5 + 6 + int pdsc_fw_reporter_diagnose(struct devlink_health_reporter *reporter, 7 + struct devlink_fmsg *fmsg, 8 + struct netlink_ext_ack *extack) 9 + { 10 + struct pdsc *pdsc = devlink_health_reporter_priv(reporter); 11 + int err; 12 + 13 + mutex_lock(&pdsc->config_lock); 14 + 15 + if (test_bit(PDSC_S_FW_DEAD, &pdsc->state)) 16 + err = devlink_fmsg_string_pair_put(fmsg, "Status", "dead"); 17 + else if (!pdsc_is_fw_good(pdsc)) 18 + err = devlink_fmsg_string_pair_put(fmsg, "Status", "unhealthy"); 19 + else 20 + err = devlink_fmsg_string_pair_put(fmsg, "Status", "healthy"); 21 + 22 + mutex_unlock(&pdsc->config_lock); 23 + 24 + if (err) 25 + return err; 26 + 27 + err = devlink_fmsg_u32_pair_put(fmsg, "State", 28 + pdsc->fw_status & 29 + ~PDS_CORE_FW_STS_F_GENERATION); 30 + if (err) 31 + return err; 32 + 33 + err = devlink_fmsg_u32_pair_put(fmsg, "Generation", 34 + pdsc->fw_generation >> 4); 35 + if (err) 36 + return err; 37 + 38 + return devlink_fmsg_u32_pair_put(fmsg, "Recoveries", 39 + pdsc->fw_recoveries); 40 + }
+22
drivers/net/ethernet/amd/pds_core/main.c
··· 130 130 return -1; 131 131 } 132 132 133 + static const struct devlink_health_reporter_ops pdsc_fw_reporter_ops = { 134 + .name = "fw", 135 + .diagnose = pdsc_fw_reporter_diagnose, 136 + }; 137 + 133 138 #define PDSC_WQ_NAME_LEN 24 134 139 135 140 static int pdsc_init_pf(struct pdsc *pdsc) 136 141 { 142 + struct devlink_health_reporter *hr; 137 143 char wq_name[PDSC_WQ_NAME_LEN]; 138 144 struct devlink *dl; 139 145 int err; ··· 178 172 179 173 dl = priv_to_devlink(pdsc); 180 174 devl_lock(dl); 175 + 176 + hr = devl_health_reporter_create(dl, &pdsc_fw_reporter_ops, 0, pdsc); 177 + if (IS_ERR(hr)) { 178 + dev_warn(pdsc->dev, "Failed to create fw reporter: %pe\n", hr); 179 + err = PTR_ERR(hr); 180 + devl_unlock(dl); 181 + goto err_out_teardown; 182 + } 183 + pdsc->fw_reporter = hr; 184 + 181 185 devl_register(dl); 182 186 devl_unlock(dl); 183 187 ··· 196 180 197 181 return 0; 198 182 183 + err_out_teardown: 184 + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); 199 185 err_out_unmap_bars: 200 186 mutex_unlock(&pdsc->config_lock); 201 187 del_timer_sync(&pdsc->wdtimer); ··· 301 283 dl = priv_to_devlink(pdsc); 302 284 devl_lock(dl); 303 285 devl_unregister(dl); 286 + if (pdsc->fw_reporter) { 287 + devl_health_reporter_destroy(pdsc->fw_reporter); 288 + pdsc->fw_reporter = NULL; 289 + } 304 290 devl_unlock(dl); 305 291 306 292 if (!pdev->is_virtfn) {