| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/22 15:26 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"NET_VENDOR_META",
"FBNIC",
"HWMON"
],
"FocusSymbols": [
"fbnic_fw_parse_threshold_exceeded_resp",
"fbnic_fw_parse_cap_resp",
"fbnic_hwmon_temp_read",
"fbnic_hwmon_in_read",
"fbnic_hwmon_sensor_read",
"fbnic_hwmon_notify_event",
"fbnic_hwmon_read",
"fbnic_hwmon_read_threshold",
"fbnic_hwmon_read_alarm"
],
"Reasoning": "The patch adds hardware monitoring threshold and alarm support to the fbnic driver. It introduces new sysfs read handlers for temperature and voltage sensors, and adds a firmware message parser for threshold exceeded events. These are functional changes to the driver's hwmon interface and firmware mailbox processing, which can be fuzzed via sysfs and emulated PCI/mailbox interactions.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/22 15:26 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit c6f81a62080229189da10902bdb82236092bfb67\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jul 22 15:26:51 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h\nindex d0715695c43e75..4a49c20e4a014c 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic.h\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h\n@@ -22,11 +22,18 @@ struct fbnic_napi_vector;\n #define FBNIC_MAX_NAPI_VECTORS\t\t128u\n #define FBNIC_MBX_CMPL_SLOTS\t\t4\n \n+struct fbnic_hwmon_cache {\n+\tunsigned long last_read;\n+\ts32 temp_mdeg;\n+\ts32 volt_mv;\n+};\n+\n struct fbnic_dev {\n \tstruct device *dev;\n \tstruct net_device *netdev;\n \tstruct dentry *dbg_fbd;\n \tstruct device *hwmon;\n+\tstruct fbnic_hwmon_cache hwmon_cache;\n \tstruct devlink_health_reporter *fw_reporter;\n \tstruct devlink_health_reporter *otp_reporter;\n \n@@ -185,6 +192,7 @@ void fbnic_fw_free_mbx(struct fbnic_dev *fbd);\n \n void fbnic_hwmon_register(struct fbnic_dev *fbd);\n void fbnic_hwmon_unregister(struct fbnic_dev *fbd);\n+void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id, long val);\n \n int fbnic_mac_request_irq(struct fbnic_dev *fbd);\n void fbnic_mac_free_irq(struct fbnic_dev *fbd);\ndiff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c\nindex 283d25fae79e78..6dca38076d7b9e 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c\n@@ -575,6 +575,11 @@ static const struct fbnic_tlv_index fbnic_fw_cap_resp_index[] = {\n \tFBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_UEFI_COMMIT_STR,\n \t\t\t FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),\n \tFBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_TEMP_MIN),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_TEMP_MAX),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_TEMP_CRIT),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_VOLT_MIN),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_VOLT_MAX),\n \tFBNIC_TLV_ATTR_LAST\n };\n \n@@ -702,6 +707,22 @@ static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)\n \t/* Always assume we need a BMC reinit */\n \tfbd-\u003efw_cap.need_bmc_tcam_reinit = true;\n \n+\tfbd-\u003efw_cap.temp.min =\n+\t\tfbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_TEMP_MIN],\n+\t\t\t\t\t FBNIC_SENSOR_NO_DATA);\n+\tfbd-\u003efw_cap.temp.max =\n+\t\tfbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_TEMP_MAX],\n+\t\t\t\t\t FBNIC_SENSOR_NO_DATA);\n+\tfbd-\u003efw_cap.temp.crit =\n+\t\tfbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_TEMP_CRIT],\n+\t\t\t\t\t FBNIC_SENSOR_NO_DATA);\n+\tfbd-\u003efw_cap.volt.min =\n+\t\tfbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_VOLT_MIN],\n+\t\t\t\t\t FBNIC_SENSOR_NO_DATA);\n+\tfbd-\u003efw_cap.volt.max =\n+\t\tfbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_VOLT_MAX],\n+\t\t\t\t\t FBNIC_SENSOR_NO_DATA);\n+\n \treturn 0;\n }\n \n@@ -1618,6 +1639,57 @@ fbnic_fw_parser_test(void *opaque, struct fbnic_tlv_msg **results)\n \treturn err;\n }\n \n+static const struct fbnic_tlv_index fbnic_threshold_exceeded_resp_index[] = {\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERM_EXCEEDED_FLAG),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLT_EXCEEDED_FLAG),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERMAL),\n+\tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLTAGE),\n+\tFBNIC_TLV_ATTR_LAST\n+};\n+\n+static int fbnic_fw_parse_threshold_exceeded_resp(void *opaque,\n+\t\t\t\t\t\t struct fbnic_tlv_msg **results)\n+{\n+\tbool therm_exceeded, volt_exceeded;\n+\tstruct fbnic_dev *fbd = opaque;\n+\ts32 value;\n+\n+\ttherm_exceeded =\n+\t\tfta_get_sint(results, FBNIC_FW_TSENE_THERM_EXCEEDED_FLAG);\n+\tvolt_exceeded =\n+\t\tfta_get_sint(results, FBNIC_FW_TSENE_VOLT_EXCEEDED_FLAG);\n+\n+\tif (!therm_exceeded \u0026\u0026 !volt_exceeded) {\n+\t\tdev_err(fbd-\u003edev,\n+\t\t\t\"Threshold exceeded message with no flag set\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (therm_exceeded) {\n+\t\tif (!results[FBNIC_FW_TSENE_THERMAL]) {\n+\t\t\tdev_err(fbd-\u003edev,\n+\t\t\t\t\"Thermal threshold exceeded but no value received\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tvalue = fta_get_sint(results, FBNIC_FW_TSENE_THERMAL);\n+\t\tdev_err(fbd-\u003edev, \"Thermal threshold exceeded: %d mC\\n\", value);\n+\t\tfbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_TEMP, value);\n+\t}\n+\n+\tif (volt_exceeded) {\n+\t\tif (!results[FBNIC_FW_TSENE_VOLTAGE]) {\n+\t\t\tdev_err(fbd-\u003edev,\n+\t\t\t\t\"Voltage threshold exceeded but no value received\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tvalue = fta_get_sint(results, FBNIC_FW_TSENE_VOLTAGE);\n+\t\tdev_err(fbd-\u003edev, \"Voltage threshold exceeded: %d mV\\n\", value);\n+\t\tfbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_VOLTAGE, value);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {\n \tFBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, fbnic_fw_parser_test),\n \tFBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index,\n@@ -1646,6 +1718,9 @@ static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {\n \tFBNIC_TLV_PARSER(TSENE_READ_RESP,\n \t\t\t fbnic_tsene_read_resp_index,\n \t\t\t fbnic_fw_parse_tsene_read_resp),\n+\tFBNIC_TLV_PARSER(SENSOR_THRESHOLD_EXCEEDED_RESP,\n+\t\t\t fbnic_threshold_exceeded_resp_index,\n+\t\t\t fbnic_fw_parse_threshold_exceeded_resp),\n \tFBNIC_TLV_PARSER(LOG_MSG_REQ,\n \t\t\t fbnic_fw_log_req_index,\n \t\t\t fbnic_fw_parse_log_req),\ndiff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h\nindex d84723e4cfa362..87301e6082555f 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h\n@@ -6,6 +6,7 @@\n \n #include \u003clinux/completion.h\u003e\n #include \u003clinux/if_ether.h\u003e\n+#include \u003clinux/limits.h\u003e\n #include \u003clinux/types.h\u003e\n \n struct fbnic_dev;\n@@ -44,6 +45,18 @@ struct fbnic_fw_ver {\n \tchar commit[FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE];\n };\n \n+/* Sentinel for a sensor value the driver does not have: a threshold the\n+ * firmware never populated (older firmware) or a cache entry not yet\n+ * refreshed.\n+ */\n+#define FBNIC_SENSOR_NO_DATA\t\t\tS32_MIN\n+\n+struct fbnic_threshold {\n+\ts32 min;\n+\ts32 max;\n+\ts32 crit;\n+};\n+\n struct fbnic_fw_cap {\n \tstruct {\n \t\tstruct fbnic_fw_ver mgmt, bootloader;\n@@ -60,6 +73,8 @@ struct fbnic_fw_cap {\n \tu8\tlink_speed;\n \tu8\tlink_fec;\n \tu32\tanti_rollback_version;\n+\tstruct fbnic_threshold temp;\n+\tstruct fbnic_threshold volt;\n };\n \n struct fbnic_fw_completion {\n@@ -212,6 +227,7 @@ enum {\n \tFBNIC_TLV_MSG_ID_QSFP_READ_RESP\t\t\t= 0x39,\n \tFBNIC_TLV_MSG_ID_TSENE_READ_REQ\t\t\t= 0x3C,\n \tFBNIC_TLV_MSG_ID_TSENE_READ_RESP\t\t= 0x3D,\n+\tFBNIC_TLV_MSG_ID_SENSOR_THRESHOLD_EXCEEDED_RESP = 0x40,\n \tFBNIC_TLV_MSG_ID_LOG_SEND_LOGS_REQ\t\t= 0x43,\n \tFBNIC_TLV_MSG_ID_LOG_MSG_REQ\t\t\t= 0x44,\n \tFBNIC_TLV_MSG_ID_LOG_MSG_RESP\t\t\t= 0x45,\n@@ -242,6 +258,12 @@ enum {\n \tFBNIC_FW_CAP_RESP_UEFI_VERSION\t\t\t= 0x11,\n \tFBNIC_FW_CAP_RESP_UEFI_COMMIT_STR\t\t= 0x12,\n \tFBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION\t\t= 0x15,\n+\t/* 0x16 and 0x17 are reserved for future use */\n+\tFBNIC_FW_CAP_RESP_TEMP_MIN\t\t\t= 0x18,\n+\tFBNIC_FW_CAP_RESP_TEMP_MAX\t\t\t= 0x19,\n+\tFBNIC_FW_CAP_RESP_TEMP_CRIT\t\t\t= 0x1a,\n+\tFBNIC_FW_CAP_RESP_VOLT_MIN\t\t\t= 0x1b,\n+\tFBNIC_FW_CAP_RESP_VOLT_MAX\t\t\t= 0x1c,\n \tFBNIC_FW_CAP_RESP_MSG_MAX\n };\n \n@@ -275,6 +297,14 @@ enum {\n \tFBNIC_FW_TSENE_MSG_MAX\n };\n \n+enum {\n+\tFBNIC_FW_TSENE_THERM_EXCEEDED_FLAG\t= 0x0,\n+\tFBNIC_FW_TSENE_VOLT_EXCEEDED_FLAG\t= 0x1,\n+\tFBNIC_FW_TSENE_THERMAL\t\t\t= 0x2,\n+\tFBNIC_FW_TSENE_VOLTAGE\t\t\t= 0x3,\n+\tFBNIC_FW_TSENE_EXCEEDED_MSG_MAX,\n+};\n+\n enum {\n \tFBNIC_FW_OWNERSHIP_FLAG\t\t\t= 0x0,\n \tFBNIC_FW_OWNERSHIP_TIME\t\t\t= 0x1,\ndiff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c\nindex def8598aceecf7..eb910ba47f3789 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c\n@@ -2,41 +2,184 @@\n /* Copyright (c) Meta Platforms, Inc. and affiliates. */\n \n #include \u003clinux/hwmon.h\u003e\n+#include \u003clinux/jiffies.h\u003e\n \n #include \"fbnic.h\"\n #include \"fbnic_mac.h\"\n \n-static int fbnic_hwmon_sensor_id(enum hwmon_sensor_types type)\n+static umode_t fbnic_hwmon_is_visible(const void *drvdata,\n+\t\t\t\t enum hwmon_sensor_types type,\n+\t\t\t\t u32 attr, int channel)\n {\n-\tif (type == hwmon_temp)\n-\t\treturn FBNIC_SENSOR_TEMP;\n-\tif (type == hwmon_in)\n-\t\treturn FBNIC_SENSOR_VOLTAGE;\n+\treturn 0444;\n+}\n \n-\treturn -EOPNOTSUPP;\n+static int fbnic_hwmon_sensor_read(struct fbnic_dev *fbd, int id, long *val)\n+{\n+\tstruct fbnic_hwmon_cache *cache = \u0026fbd-\u003ehwmon_cache;\n+\tstruct fbnic_fw_completion *fw_cmpl;\n+\tint err = 0;\n+\ts32 *cached;\n+\n+\tswitch (id) {\n+\tcase FBNIC_SENSOR_TEMP:\n+\t\tcached = \u0026cache-\u003etemp_mdeg;\n+\t\tbreak;\n+\tcase FBNIC_SENSOR_VOLTAGE:\n+\t\tcached = \u0026cache-\u003evolt_mv;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (*cached != FBNIC_SENSOR_NO_DATA \u0026\u0026\n+\t time_is_after_eq_jiffies(cache-\u003elast_read)) {\n+\t\t*val = *cached;\n+\t\treturn 0;\n+\t}\n+\n+\tfw_cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_TSENE_READ_RESP);\n+\tif (!fw_cmpl)\n+\t\treturn -ENOMEM;\n+\n+\terr = fbnic_fw_xmit_tsene_read_msg(fbd, fw_cmpl);\n+\tif (err) {\n+\t\tdev_err(fbd-\u003edev,\n+\t\t\t\"Failed to transmit TSENE read msg, err %d\\n\",\n+\t\t\terr);\n+\t\tgoto exit_free;\n+\t}\n+\n+\tif (!wait_for_completion_timeout(\u0026fw_cmpl-\u003edone, 10 * HZ)) {\n+\t\tdev_err(fbd-\u003edev, \"Timed out waiting for TSENE read\\n\");\n+\t\terr = -ETIMEDOUT;\n+\t\tgoto exit_cleanup;\n+\t}\n+\n+\t/* Handle error returned by firmware */\n+\tif (fw_cmpl-\u003eresult) {\n+\t\terr = fw_cmpl-\u003eresult;\n+\t\tdev_err(fbd-\u003edev, \"%s: Firmware returned error %d\\n\",\n+\t\t\t__func__, err);\n+\t\tgoto exit_cleanup;\n+\t}\n+\n+\t/* FW returns both readings in one response, cache both. */\n+\tcache-\u003etemp_mdeg = fw_cmpl-\u003eu.tsene.millidegrees;\n+\tcache-\u003evolt_mv = fw_cmpl-\u003eu.tsene.millivolts;\n+\tcache-\u003elast_read = jiffies;\n+\n+\t*val = *cached;\n+exit_cleanup:\n+\tfbnic_mbx_clear_cmpl(fbd, fw_cmpl);\n+exit_free:\n+\tfbnic_fw_put_cmpl(fw_cmpl);\n+\n+\treturn err;\n }\n \n-static umode_t fbnic_hwmon_is_visible(const void *drvdata,\n-\t\t\t\t enum hwmon_sensor_types type,\n-\t\t\t\t u32 attr, int channel)\n+static int fbnic_hwmon_read_threshold(long thr, long *val)\n+{\n+\tif (thr == FBNIC_SENSOR_NO_DATA)\n+\t\treturn -ENODATA;\n+\n+\t*val = thr;\n+\treturn 0;\n+}\n+\n+static int fbnic_hwmon_read_alarm(long a, long b, long *val)\n {\n-\tif (type == hwmon_temp \u0026\u0026 attr == hwmon_temp_input)\n-\t\treturn 0444;\n-\tif (type == hwmon_in \u0026\u0026 attr == hwmon_in_input)\n-\t\treturn 0444;\n+\tif (a == FBNIC_SENSOR_NO_DATA || b == FBNIC_SENSOR_NO_DATA)\n+\t\treturn -ENODATA;\n \n+\t*val = a \u003e= b;\n \treturn 0;\n }\n \n+static int fbnic_hwmon_temp_read(struct fbnic_dev *fbd, u32 attr, long *val)\n+{\n+\tint err;\n+\n+\tswitch (attr) {\n+\tcase hwmon_temp_min:\n+\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.temp.min, val);\n+\tcase hwmon_temp_max:\n+\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.temp.max, val);\n+\tcase hwmon_temp_crit:\n+\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.temp.crit, val);\n+\tcase hwmon_temp_input:\n+\tcase hwmon_temp_min_alarm:\n+\tcase hwmon_temp_max_alarm:\n+\tcase hwmon_temp_crit_alarm:\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\terr = fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_TEMP, val);\n+\tif (err)\n+\t\treturn err;\n+\n+\tswitch (attr) {\n+\tcase hwmon_temp_input:\n+\t\treturn 0;\n+\tcase hwmon_temp_min_alarm:\n+\t\treturn fbnic_hwmon_read_alarm(fbd-\u003efw_cap.temp.min, *val, val);\n+\tcase hwmon_temp_max_alarm:\n+\t\treturn fbnic_hwmon_read_alarm(*val, fbd-\u003efw_cap.temp.max, val);\n+\tcase hwmon_temp_crit_alarm:\n+\t\treturn fbnic_hwmon_read_alarm(*val, fbd-\u003efw_cap.temp.crit, val);\n+\t}\n+\n+\treturn -EOPNOTSUPP;\n+}\n+\n+static int fbnic_hwmon_in_read(struct fbnic_dev *fbd, u32 attr, long *val)\n+{\n+\tint err;\n+\n+\tswitch (attr) {\n+\tcase hwmon_in_min:\n+\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.volt.min, val);\n+\tcase hwmon_in_max:\n+\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.volt.max, val);\n+\tcase hwmon_in_input:\n+\tcase hwmon_in_min_alarm:\n+\tcase hwmon_in_max_alarm:\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\terr = fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_VOLTAGE, val);\n+\tif (err)\n+\t\treturn err;\n+\n+\tswitch (attr) {\n+\tcase hwmon_in_input:\n+\t\treturn 0;\n+\tcase hwmon_in_min_alarm:\n+\t\treturn fbnic_hwmon_read_alarm(fbd-\u003efw_cap.volt.min, *val, val);\n+\tcase hwmon_in_max_alarm:\n+\t\treturn fbnic_hwmon_read_alarm(*val, fbd-\u003efw_cap.volt.max, val);\n+\t}\n+\n+\treturn -EOPNOTSUPP;\n+}\n+\n static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,\n \t\t\t u32 attr, int channel, long *val)\n {\n \tstruct fbnic_dev *fbd = dev_get_drvdata(dev);\n-\tconst struct fbnic_mac *mac = fbd-\u003emac;\n-\tint id;\n \n-\tid = fbnic_hwmon_sensor_id(type);\n-\treturn id \u003c 0 ? id : mac-\u003eget_sensor(fbd, id, val);\n+\tswitch (type) {\n+\tcase hwmon_temp:\n+\t\treturn fbnic_hwmon_temp_read(fbd, attr, val);\n+\tcase hwmon_in:\n+\t\treturn fbnic_hwmon_in_read(fbd, attr, val);\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n }\n \n static const struct hwmon_ops fbnic_hwmon_ops = {\n@@ -45,8 +188,15 @@ static const struct hwmon_ops fbnic_hwmon_ops = {\n };\n \n static const struct hwmon_channel_info *fbnic_hwmon_info[] = {\n-\tHWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),\n-\tHWMON_CHANNEL_INFO(in, HWMON_I_INPUT),\n+\tHWMON_CHANNEL_INFO(temp,\n+\t\t\t HWMON_T_INPUT |\n+\t\t\t HWMON_T_MIN | HWMON_T_MIN_ALARM |\n+\t\t\t HWMON_T_MAX | HWMON_T_MAX_ALARM |\n+\t\t\t HWMON_T_CRIT | HWMON_T_CRIT_ALARM),\n+\tHWMON_CHANNEL_INFO(in,\n+\t\t\t HWMON_I_INPUT |\n+\t\t\t HWMON_I_MIN | HWMON_I_MIN_ALARM |\n+\t\t\t HWMON_I_MAX | HWMON_I_MAX_ALARM),\n \tNULL\n };\n \n@@ -57,25 +207,81 @@ static const struct hwmon_chip_info fbnic_chip_info = {\n \n void fbnic_hwmon_register(struct fbnic_dev *fbd)\n {\n+\tstruct device *hwmon;\n+\n \tif (!IS_REACHABLE(CONFIG_HWMON))\n \t\treturn;\n \n-\tfbd-\u003ehwmon = hwmon_device_register_with_info(fbd-\u003edev, \"fbnic\",\n-\t\t\t\t\t\t fbd, \u0026fbnic_chip_info,\n-\t\t\t\t\t\t NULL);\n-\tif (IS_ERR(fbd-\u003ehwmon)) {\n+\t/* Seed cache with sentinel so the first read always refreshes. */\n+\tfbd-\u003ehwmon_cache.temp_mdeg = FBNIC_SENSOR_NO_DATA;\n+\tfbd-\u003ehwmon_cache.volt_mv = FBNIC_SENSOR_NO_DATA;\n+\n+\thwmon = hwmon_device_register_with_info(fbd-\u003edev, \"fbnic\", fbd,\n+\t\t\t\t\t\t\u0026fbnic_chip_info, NULL);\n+\tif (IS_ERR(hwmon)) {\n \t\tdev_notice(fbd-\u003edev,\n \t\t\t \"Failed to register hwmon device %pe\\n\",\n-\t\t\t fbd-\u003ehwmon);\n-\t\tfbd-\u003ehwmon = NULL;\n+\t\t\t hwmon);\n+\t\treturn;\n \t}\n+\n+\tWRITE_ONCE(fbd-\u003ehwmon, hwmon);\n }\n \n void fbnic_hwmon_unregister(struct fbnic_dev *fbd)\n {\n+\tstruct device *hwmon;\n+\n \tif (!IS_REACHABLE(CONFIG_HWMON) || !fbd-\u003ehwmon)\n \t\treturn;\n \n-\thwmon_device_unregister(fbd-\u003ehwmon);\n-\tfbd-\u003ehwmon = NULL;\n+\thwmon = fbd-\u003ehwmon;\n+\t/* Pair with READ_ONCE() in fbnic_hwmon_notify_event(). Publish NULL\n+\t * and wait for any in-flight FW mailbox IRQ handler to finish so it\n+\t * cannot dereference the hwmon device after we unregister it.\n+\t */\n+\tWRITE_ONCE(fbd-\u003ehwmon, NULL);\n+\tsynchronize_irq(fbd-\u003efw_msix_vector);\n+\n+\thwmon_device_unregister(hwmon);\n+}\n+\n+void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id, long val)\n+{\n+\tenum hwmon_sensor_types type;\n+\tstruct device *hwmon;\n+\ts32 attr = -1;\n+\n+\tswitch (id) {\n+\tcase FBNIC_SENSOR_TEMP:\n+\t\ttype = hwmon_temp;\n+\n+\t\tif (val \u003c= fbd-\u003efw_cap.temp.min)\n+\t\t\tattr = hwmon_temp_min_alarm;\n+\t\telse if (val \u003e= fbd-\u003efw_cap.temp.crit)\n+\t\t\tattr = hwmon_temp_crit_alarm;\n+\t\telse if (val \u003e= fbd-\u003efw_cap.temp.max)\n+\t\t\tattr = hwmon_temp_max_alarm;\n+\n+\t\tbreak;\n+\tcase FBNIC_SENSOR_VOLTAGE:\n+\t\ttype = hwmon_in;\n+\n+\t\tif (val \u003c= fbd-\u003efw_cap.volt.min)\n+\t\t\tattr = hwmon_in_min_alarm;\n+\t\telse if (val \u003e= fbd-\u003efw_cap.volt.max)\n+\t\t\tattr = hwmon_in_max_alarm;\n+\n+\t\tbreak;\n+\tdefault:\n+\t\treturn;\n+\t}\n+\n+\t/* Pair with WRITE_ONCE() in fbnic_hwmon_unregister(). Skip the\n+\t * notification if hwmon failed to register or has already been torn\n+\t * down.\n+\t */\n+\thwmon = READ_ONCE(fbd-\u003ehwmon);\n+\tif (attr \u003e= 0 \u0026\u0026 hwmon)\n+\t\thwmon_notify_event(hwmon, type, attr, 0);\n }\ndiff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c\nindex 53b7a938b4c277..fba2e2efaeb8c7 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c\n@@ -899,60 +899,6 @@ fbnic_mac_get_rmon_stats(struct fbnic_dev *fbd, bool reset,\n \t\t\t TMI_STAT_TX_PACKET_9217_MAX_BYTES);\n }\n \n-static int fbnic_mac_get_sensor_asic(struct fbnic_dev *fbd, int id,\n-\t\t\t\t long *val)\n-{\n-\tstruct fbnic_fw_completion *fw_cmpl;\n-\tint err = 0;\n-\ts32 *sensor;\n-\n-\tfw_cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_TSENE_READ_RESP);\n-\tif (!fw_cmpl)\n-\t\treturn -ENOMEM;\n-\n-\tswitch (id) {\n-\tcase FBNIC_SENSOR_TEMP:\n-\t\tsensor = \u0026fw_cmpl-\u003eu.tsene.millidegrees;\n-\t\tbreak;\n-\tcase FBNIC_SENSOR_VOLTAGE:\n-\t\tsensor = \u0026fw_cmpl-\u003eu.tsene.millivolts;\n-\t\tbreak;\n-\tdefault:\n-\t\terr = -EINVAL;\n-\t\tgoto exit_free;\n-\t}\n-\n-\terr = fbnic_fw_xmit_tsene_read_msg(fbd, fw_cmpl);\n-\tif (err) {\n-\t\tdev_err(fbd-\u003edev,\n-\t\t\t\"Failed to transmit TSENE read msg, err %d\\n\",\n-\t\t\terr);\n-\t\tgoto exit_free;\n-\t}\n-\n-\tif (!wait_for_completion_timeout(\u0026fw_cmpl-\u003edone, 10 * HZ)) {\n-\t\tdev_err(fbd-\u003edev, \"Timed out waiting for TSENE read\\n\");\n-\t\terr = -ETIMEDOUT;\n-\t\tgoto exit_cleanup;\n-\t}\n-\n-\t/* Handle error returned by firmware */\n-\tif (fw_cmpl-\u003eresult) {\n-\t\terr = fw_cmpl-\u003eresult;\n-\t\tdev_err(fbd-\u003edev, \"%s: Firmware returned error %d\\n\",\n-\t\t\t__func__, err);\n-\t\tgoto exit_cleanup;\n-\t}\n-\n-\t*val = *sensor;\n-exit_cleanup:\n-\tfbnic_mbx_clear_cmpl(fbd, fw_cmpl);\n-exit_free:\n-\tfbnic_fw_put_cmpl(fw_cmpl);\n-\n-\treturn err;\n-}\n-\n static const struct fbnic_mac fbnic_mac_asic = {\n \t.init_regs = fbnic_mac_init_regs,\n \t.get_link = fbnic_mac_get_link,\n@@ -966,7 +912,6 @@ static const struct fbnic_mac fbnic_mac_asic = {\n \t.get_rmon_stats = fbnic_mac_get_rmon_stats,\n \t.link_down = fbnic_mac_link_down_asic,\n \t.link_up = fbnic_mac_link_up_asic,\n-\t.get_sensor = fbnic_mac_get_sensor_asic,\n };\n \n /**\ndiff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h\nindex 10f30e0e8f6916..bde2daa656457b 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h\n@@ -137,8 +137,6 @@ struct fbnic_mac {\n \n \tvoid (*link_down)(struct fbnic_dev *fbd);\n \tvoid (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);\n-\n-\tint (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);\n };\n \n int fbnic_mac_init(struct fbnic_dev *fbd);\n"
} |
| 2/1 | 2026/07/22 15:26 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"NET_VENDOR_META",
"FBNIC",
"HWMON"
],
"FocusSymbols": [
"fbnic_fw_parse_threshold_exceeded_resp",
"fbnic_fw_parse_cap_resp",
"fbnic_hwmon_temp_read",
"fbnic_hwmon_in_read",
"fbnic_hwmon_sensor_read",
"fbnic_hwmon_notify_event",
"fbnic_hwmon_read",
"fbnic_hwmon_read_threshold",
"fbnic_hwmon_read_alarm"
],
"Reasoning": "The patch adds hardware monitoring threshold and alarm support to the fbnic driver. It introduces new sysfs read handlers for temperature and voltage sensors, and adds a firmware message parser for threshold exceeded events. These are functional changes to the driver's hwmon interface and firmware mailbox processing, which can be fuzzed via sysfs and emulated PCI/mailbox interactions.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit c6f81a62080229189da10902bdb82236092bfb67
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jul 22 15:26:51 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h
index d0715695c43e75..4a49c20e4a014c 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h
@@ -22,11 +22,18 @@ struct fbnic_napi_vector;
#define FBNIC_MAX_NAPI_VECTORS 128u
#define FBNIC_MBX_CMPL_SLOTS 4
+struct fbnic_hwmon_cache {
+ unsigned long last_read;
+ s32 temp_mdeg;
+ s32 volt_mv;
+};
+
struct fbnic_dev {
struct device *dev;
struct net_device *netdev;
struct dentry *dbg_fbd;
struct device *hwmon;
+ struct fbnic_hwmon_cache hwmon_cache;
struct devlink_health_reporter *fw_reporter;
struct devlink_health_reporter *otp_reporter;
@@ -185,6 +192,7 @@ void fbnic_fw_free_mbx(struct fbnic_dev *fbd);
void fbnic_hwmon_register(struct fbnic_dev *fbd);
void fbnic_hwmon_unregister(struct fbnic_dev *fbd);
+void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id, long val);
int fbnic_mac_request_irq(struct fbnic_dev *fbd);
void fbnic_mac_free_irq(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
index 283d25fae79e78..6dca38076d7b9e 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
@@ -575,6 +575,11 @@ static const struct fbnic_tlv_index fbnic_fw_cap_resp_index[] = {
FBNIC_TLV_ATTR_STRING(FBNIC_FW_CAP_RESP_UEFI_COMMIT_STR,
FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE),
FBNIC_TLV_ATTR_U32(FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_TEMP_MIN),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_TEMP_MAX),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_TEMP_CRIT),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_VOLT_MIN),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_CAP_RESP_VOLT_MAX),
FBNIC_TLV_ATTR_LAST
};
@@ -702,6 +707,22 @@ static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)
/* Always assume we need a BMC reinit */
fbd->fw_cap.need_bmc_tcam_reinit = true;
+ fbd->fw_cap.temp.min =
+ fbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_TEMP_MIN],
+ FBNIC_SENSOR_NO_DATA);
+ fbd->fw_cap.temp.max =
+ fbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_TEMP_MAX],
+ FBNIC_SENSOR_NO_DATA);
+ fbd->fw_cap.temp.crit =
+ fbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_TEMP_CRIT],
+ FBNIC_SENSOR_NO_DATA);
+ fbd->fw_cap.volt.min =
+ fbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_VOLT_MIN],
+ FBNIC_SENSOR_NO_DATA);
+ fbd->fw_cap.volt.max =
+ fbnic_tlv_attr_get_signed(results[FBNIC_FW_CAP_RESP_VOLT_MAX],
+ FBNIC_SENSOR_NO_DATA);
+
return 0;
}
@@ -1618,6 +1639,57 @@ fbnic_fw_parser_test(void *opaque, struct fbnic_tlv_msg **results)
return err;
}
+static const struct fbnic_tlv_index fbnic_threshold_exceeded_resp_index[] = {
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERM_EXCEEDED_FLAG),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLT_EXCEEDED_FLAG),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERMAL),
+ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLTAGE),
+ FBNIC_TLV_ATTR_LAST
+};
+
+static int fbnic_fw_parse_threshold_exceeded_resp(void *opaque,
+ struct fbnic_tlv_msg **results)
+{
+ bool therm_exceeded, volt_exceeded;
+ struct fbnic_dev *fbd = opaque;
+ s32 value;
+
+ therm_exceeded =
+ fta_get_sint(results, FBNIC_FW_TSENE_THERM_EXCEEDED_FLAG);
+ volt_exceeded =
+ fta_get_sint(results, FBNIC_FW_TSENE_VOLT_EXCEEDED_FLAG);
+
+ if (!therm_exceeded && !volt_exceeded) {
+ dev_err(fbd->dev,
+ "Threshold exceeded message with no flag set\n");
+ return -EINVAL;
+ }
+
+ if (therm_exceeded) {
+ if (!results[FBNIC_FW_TSENE_THERMAL]) {
+ dev_err(fbd->dev,
+ "Thermal threshold exceeded but no value received\n");
+ return -EINVAL;
+ }
+ value = fta_get_sint(results, FBNIC_FW_TSENE_THERMAL);
+ dev_err(fbd->dev, "Thermal threshold exceeded: %d mC\n", value);
+ fbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_TEMP, value);
+ }
+
+ if (volt_exceeded) {
+ if (!results[FBNIC_FW_TSENE_VOLTAGE]) {
+ dev_err(fbd->dev,
+ "Voltage threshold exceeded but no value received\n");
+ return -EINVAL;
+ }
+ value = fta_get_sint(results, FBNIC_FW_TSENE_VOLTAGE);
+ dev_err(fbd->dev, "Voltage threshold exceeded: %d mV\n", value);
+ fbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_VOLTAGE, value);
+ }
+
+ return 0;
+}
+
static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
FBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, fbnic_fw_parser_test),
FBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index,
@@ -1646,6 +1718,9 @@ static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
FBNIC_TLV_PARSER(TSENE_READ_RESP,
fbnic_tsene_read_resp_index,
fbnic_fw_parse_tsene_read_resp),
+ FBNIC_TLV_PARSER(SENSOR_THRESHOLD_EXCEEDED_RESP,
+ fbnic_threshold_exceeded_resp_index,
+ fbnic_fw_parse_threshold_exceeded_resp),
FBNIC_TLV_PARSER(LOG_MSG_REQ,
fbnic_fw_log_req_index,
fbnic_fw_parse_log_req),
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
index d84723e4cfa362..87301e6082555f 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
@@ -6,6 +6,7 @@
#include <linux/completion.h>
#include <linux/if_ether.h>
+#include <linux/limits.h>
#include <linux/types.h>
struct fbnic_dev;
@@ -44,6 +45,18 @@ struct fbnic_fw_ver {
char commit[FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE];
};
+/* Sentinel for a sensor value the driver does not have: a threshold the
+ * firmware never populated (older firmware) or a cache entry not yet
+ * refreshed.
+ */
+#define FBNIC_SENSOR_NO_DATA S32_MIN
+
+struct fbnic_threshold {
+ s32 min;
+ s32 max;
+ s32 crit;
+};
+
struct fbnic_fw_cap {
struct {
struct fbnic_fw_ver mgmt, bootloader;
@@ -60,6 +73,8 @@ struct fbnic_fw_cap {
u8 link_speed;
u8 link_fec;
u32 anti_rollback_version;
+ struct fbnic_threshold temp;
+ struct fbnic_threshold volt;
};
struct fbnic_fw_completion {
@@ -212,6 +227,7 @@ enum {
FBNIC_TLV_MSG_ID_QSFP_READ_RESP = 0x39,
FBNIC_TLV_MSG_ID_TSENE_READ_REQ = 0x3C,
FBNIC_TLV_MSG_ID_TSENE_READ_RESP = 0x3D,
+ FBNIC_TLV_MSG_ID_SENSOR_THRESHOLD_EXCEEDED_RESP = 0x40,
FBNIC_TLV_MSG_ID_LOG_SEND_LOGS_REQ = 0x43,
FBNIC_TLV_MSG_ID_LOG_MSG_REQ = 0x44,
FBNIC_TLV_MSG_ID_LOG_MSG_RESP = 0x45,
@@ -242,6 +258,12 @@ enum {
FBNIC_FW_CAP_RESP_UEFI_VERSION = 0x11,
FBNIC_FW_CAP_RESP_UEFI_COMMIT_STR = 0x12,
FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION = 0x15,
+ /* 0x16 and 0x17 are reserved for future use */
+ FBNIC_FW_CAP_RESP_TEMP_MIN = 0x18,
+ FBNIC_FW_CAP_RESP_TEMP_MAX = 0x19,
+ FBNIC_FW_CAP_RESP_TEMP_CRIT = 0x1a,
+ FBNIC_FW_CAP_RESP_VOLT_MIN = 0x1b,
+ FBNIC_FW_CAP_RESP_VOLT_MAX = 0x1c,
FBNIC_FW_CAP_RESP_MSG_MAX
};
@@ -275,6 +297,14 @@ enum {
FBNIC_FW_TSENE_MSG_MAX
};
+enum {
+ FBNIC_FW_TSENE_THERM_EXCEEDED_FLAG = 0x0,
+ FBNIC_FW_TSENE_VOLT_EXCEEDED_FLAG = 0x1,
+ FBNIC_FW_TSENE_THERMAL = 0x2,
+ FBNIC_FW_TSENE_VOLTAGE = 0x3,
+ FBNIC_FW_TSENE_EXCEEDED_MSG_MAX,
+};
+
enum {
FBNIC_FW_OWNERSHIP_FLAG = 0x0,
FBNIC_FW_OWNERSHIP_TIME = 0x1,
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
index def8598aceecf7..eb910ba47f3789 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
@@ -2,41 +2,184 @@
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
#include <linux/hwmon.h>
+#include <linux/jiffies.h>
#include "fbnic.h"
#include "fbnic_mac.h"
-static int fbnic_hwmon_sensor_id(enum hwmon_sensor_types type)
+static umode_t fbnic_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
{
- if (type == hwmon_temp)
- return FBNIC_SENSOR_TEMP;
- if (type == hwmon_in)
- return FBNIC_SENSOR_VOLTAGE;
+ return 0444;
+}
- return -EOPNOTSUPP;
+static int fbnic_hwmon_sensor_read(struct fbnic_dev *fbd, int id, long *val)
+{
+ struct fbnic_hwmon_cache *cache = &fbd->hwmon_cache;
+ struct fbnic_fw_completion *fw_cmpl;
+ int err = 0;
+ s32 *cached;
+
+ switch (id) {
+ case FBNIC_SENSOR_TEMP:
+ cached = &cache->temp_mdeg;
+ break;
+ case FBNIC_SENSOR_VOLTAGE:
+ cached = &cache->volt_mv;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (*cached != FBNIC_SENSOR_NO_DATA &&
+ time_is_after_eq_jiffies(cache->last_read)) {
+ *val = *cached;
+ return 0;
+ }
+
+ fw_cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_TSENE_READ_RESP);
+ if (!fw_cmpl)
+ return -ENOMEM;
+
+ err = fbnic_fw_xmit_tsene_read_msg(fbd, fw_cmpl);
+ if (err) {
+ dev_err(fbd->dev,
+ "Failed to transmit TSENE read msg, err %d\n",
+ err);
+ goto exit_free;
+ }
+
+ if (!wait_for_completion_timeout(&fw_cmpl->done, 10 * HZ)) {
+ dev_err(fbd->dev, "Timed out waiting for TSENE read\n");
+ err = -ETIMEDOUT;
+ goto exit_cleanup;
+ }
+
+ /* Handle error returned by firmware */
+ if (fw_cmpl->result) {
+ err = fw_cmpl->result;
+ dev_err(fbd->dev, "%s: Firmware returned error %d\n",
+ __func__, err);
+ goto exit_cleanup;
+ }
+
+ /* FW returns both readings in one response, cache both. */
+ cache->temp_mdeg = fw_cmpl->u.tsene.millidegrees;
+ cache->volt_mv = fw_cmpl->u.tsene.millivolts;
+ cache->last_read = jiffies;
+
+ *val = *cached;
+exit_cleanup:
+ fbnic_mbx_clear_cmpl(fbd, fw_cmpl);
+exit_free:
+ fbnic_fw_put_cmpl(fw_cmpl);
+
+ return err;
}
-static umode_t fbnic_hwmon_is_visible(const void *drvdata,
- enum hwmon_sensor_types type,
- u32 attr, int channel)
+static int fbnic_hwmon_read_threshold(long thr, long *val)
+{
+ if (thr == FBNIC_SENSOR_NO_DATA)
+ return -ENODATA;
+
+ *val = thr;
+ return 0;
+}
+
+static int fbnic_hwmon_read_alarm(long a, long b, long *val)
{
- if (type == hwmon_temp && attr == hwmon_temp_input)
- return 0444;
- if (type == hwmon_in && attr == hwmon_in_input)
- return 0444;
+ if (a == FBNIC_SENSOR_NO_DATA || b == FBNIC_SENSOR_NO_DATA)
+ return -ENODATA;
+ *val = a >= b;
return 0;
}
+static int fbnic_hwmon_temp_read(struct fbnic_dev *fbd, u32 attr, long *val)
+{
+ int err;
+
+ switch (attr) {
+ case hwmon_temp_min:
+ return fbnic_hwmon_read_threshold(fbd->fw_cap.temp.min, val);
+ case hwmon_temp_max:
+ return fbnic_hwmon_read_threshold(fbd->fw_cap.temp.max, val);
+ case hwmon_temp_crit:
+ return fbnic_hwmon_read_threshold(fbd->fw_cap.temp.crit, val);
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_crit_alarm:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_TEMP, val);
+ if (err)
+ return err;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0;
+ case hwmon_temp_min_alarm:
+ return fbnic_hwmon_read_alarm(fbd->fw_cap.temp.min, *val, val);
+ case hwmon_temp_max_alarm:
+ return fbnic_hwmon_read_alarm(*val, fbd->fw_cap.temp.max, val);
+ case hwmon_temp_crit_alarm:
+ return fbnic_hwmon_read_alarm(*val, fbd->fw_cap.temp.crit, val);
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int fbnic_hwmon_in_read(struct fbnic_dev *fbd, u32 attr, long *val)
+{
+ int err;
+
+ switch (attr) {
+ case hwmon_in_min:
+ return fbnic_hwmon_read_threshold(fbd->fw_cap.volt.min, val);
+ case hwmon_in_max:
+ return fbnic_hwmon_read_threshold(fbd->fw_cap.volt.max, val);
+ case hwmon_in_input:
+ case hwmon_in_min_alarm:
+ case hwmon_in_max_alarm:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ err = fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_VOLTAGE, val);
+ if (err)
+ return err;
+
+ switch (attr) {
+ case hwmon_in_input:
+ return 0;
+ case hwmon_in_min_alarm:
+ return fbnic_hwmon_read_alarm(fbd->fw_cap.volt.min, *val, val);
+ case hwmon_in_max_alarm:
+ return fbnic_hwmon_read_alarm(*val, fbd->fw_cap.volt.max, val);
+ }
+
+ return -EOPNOTSUPP;
+}
+
static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct fbnic_dev *fbd = dev_get_drvdata(dev);
- const struct fbnic_mac *mac = fbd->mac;
- int id;
- id = fbnic_hwmon_sensor_id(type);
- return id < 0 ? id : mac->get_sensor(fbd, id, val);
+ switch (type) {
+ case hwmon_temp:
+ return fbnic_hwmon_temp_read(fbd, attr, val);
+ case hwmon_in:
+ return fbnic_hwmon_in_read(fbd, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
}
static const struct hwmon_ops fbnic_hwmon_ops = {
@@ -45,8 +188,15 @@ static const struct hwmon_ops fbnic_hwmon_ops = {
};
static const struct hwmon_channel_info *fbnic_hwmon_info[] = {
- HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
- HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT |
+ HWMON_T_MIN | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_CRIT | HWMON_T_CRIT_ALARM),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT |
+ HWMON_I_MIN | HWMON_I_MIN_ALARM |
+ HWMON_I_MAX | HWMON_I_MAX_ALARM),
NULL
};
@@ -57,25 +207,81 @@ static const struct hwmon_chip_info fbnic_chip_info = {
void fbnic_hwmon_register(struct fbnic_dev *fbd)
{
+ struct device *hwmon;
+
if (!IS_REACHABLE(CONFIG_HWMON))
return;
- fbd->hwmon = hwmon_device_register_with_info(fbd->dev, "fbnic",
- fbd, &fbnic_chip_info,
- NULL);
- if (IS_ERR(fbd->hwmon)) {
+ /* Seed cache with sentinel so the first read always refreshes. */
+ fbd->hwmon_cache.temp_mdeg = FBNIC_SENSOR_NO_DATA;
+ fbd->hwmon_cache.volt_mv = FBNIC_SENSOR_NO_DATA;
+
+ hwmon = hwmon_device_register_with_info(fbd->dev, "fbnic", fbd,
+ &fbnic_chip_info, NULL);
+ if (IS_ERR(hwmon)) {
dev_notice(fbd->dev,
"Failed to register hwmon device %pe\n",
- fbd->hwmon);
- fbd->hwmon = NULL;
+ hwmon);
+ return;
}
+
+ WRITE_ONCE(fbd->hwmon, hwmon);
}
void fbnic_hwmon_unregister(struct fbnic_dev *fbd)
{
+ struct device *hwmon;
+
if (!IS_REACHABLE(CONFIG_HWMON) || !fbd->hwmon)
return;
- hwmon_device_unregister(fbd->hwmon);
- fbd->hwmon = NULL;
+ hwmon = fbd->hwmon;
+ /* Pair with READ_ONCE() in fbnic_hwmon_notify_event(). Publish NULL
+ * and wait for any in-flight FW mailbox IRQ handler to finish so it
+ * cannot dereference the hwmon device after we unregister it.
+ */
+ WRITE_ONCE(fbd->hwmon, NULL);
+ synchronize_irq(fbd->fw_msix_vector);
+
+ hwmon_device_unregister(hwmon);
+}
+
+void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id, long val)
+{
+ enum hwmon_sensor_types type;
+ struct device *hwmon;
+ s32 attr = -1;
+
+ switch (id) {
+ case FBNIC_SENSOR_TEMP:
+ type = hwmon_temp;
+
+ if (val <= fbd->fw_cap.temp.min)
+ attr = hwmon_temp_min_alarm;
+ else if (val >= fbd->fw_cap.temp.crit)
+ attr = hwmon_temp_crit_alarm;
+ else if (val >= fbd->fw_cap.temp.max)
+ attr = hwmon_temp_max_alarm;
+
+ break;
+ case FBNIC_SENSOR_VOLTAGE:
+ type = hwmon_in;
+
+ if (val <= fbd->fw_cap.volt.min)
+ attr = hwmon_in_min_alarm;
+ else if (val >= fbd->fw_cap.volt.max)
+ attr = hwmon_in_max_alarm;
+
+ break;
+ default:
+ return;
+ }
+
+ /* Pair with WRITE_ONCE() in fbnic_hwmon_unregister(). Skip the
+ * notification if hwmon failed to register or has already been torn
+ * down.
+ */
+ hwmon = READ_ONCE(fbd->hwmon);
+ if (attr >= 0 && hwmon)
+ hwmon_notify_event(hwmon, type, attr, 0);
}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
index 53b7a938b4c277..fba2e2efaeb8c7 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
@@ -899,60 +899,6 @@ fbnic_mac_get_rmon_stats(struct fbnic_dev *fbd, bool reset,
TMI_STAT_TX_PACKET_9217_MAX_BYTES);
}
-static int fbnic_mac_get_sensor_asic(struct fbnic_dev *fbd, int id,
- long *val)
-{
- struct fbnic_fw_completion *fw_cmpl;
- int err = 0;
- s32 *sensor;
-
- fw_cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_TSENE_READ_RESP);
- if (!fw_cmpl)
- return -ENOMEM;
-
- switch (id) {
- case FBNIC_SENSOR_TEMP:
- sensor = &fw_cmpl->u.tsene.millidegrees;
- break;
- case FBNIC_SENSOR_VOLTAGE:
- sensor = &fw_cmpl->u.tsene.millivolts;
- break;
- default:
- err = -EINVAL;
- goto exit_free;
- }
-
- err = fbnic_fw_xmit_tsene_read_msg(fbd, fw_cmpl);
- if (err) {
- dev_err(fbd->dev,
- "Failed to transmit TSENE read msg, err %d\n",
- err);
- goto exit_free;
- }
-
- if (!wait_for_completion_timeout(&fw_cmpl->done, 10 * HZ)) {
- dev_err(fbd->dev, "Timed out waiting for TSENE read\n");
- err = -ETIMEDOUT;
- goto exit_cleanup;
- }
-
- /* Handle error returned by firmware */
- if (fw_cmpl->result) {
- err = fw_cmpl->result;
- dev_err(fbd->dev, "%s: Firmware returned error %d\n",
- __func__, err);
- goto exit_cleanup;
- }
-
- *val = *sensor;
-exit_cleanup:
- fbnic_mbx_clear_cmpl(fbd, fw_cmpl);
-exit_free:
- fbnic_fw_put_cmpl(fw_cmpl);
-
- return err;
-}
-
static const struct fbnic_mac fbnic_mac_asic = {
.init_regs = fbnic_mac_init_regs,
.get_link = fbnic_mac_get_link,
@@ -966,7 +912,6 @@ static const struct fbnic_mac fbnic_mac_asic = {
.get_rmon_stats = fbnic_mac_get_rmon_stats,
.link_down = fbnic_mac_link_down_asic,
.link_up = fbnic_mac_link_up_asic,
- .get_sensor = fbnic_mac_get_sensor_asic,
};
/**
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
index 10f30e0e8f6916..bde2daa656457b 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
@@ -137,8 +137,6 @@ struct fbnic_mac {
void (*link_down)(struct fbnic_dev *fbd);
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
-
- int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);
};
int fbnic_mac_init(struct fbnic_dev *fbd);
|
| 3/2 | 2026/07/22 15:26 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9905 output: 35 thoughts: 319 Thoughts: **Assessing the New Hardware Monitoring Patch for `fbnic`** Okay, so we've got a new patch. It's adding hardware monitoring features to the `fbnic` network driver, which is great. It looks like the main modifications are within `fbnic_hwmon.c`, where they've added threshold and alarm support, and are caching values. That makes sense, keeps things efficient. They've also implemented a new firmware message parser specifically for "threshold exceeded" events – `fbnic_fw_parse_threshold_exceeded_resp`. I need to dig into that; error handling and recovery in these kinds of drivers can be tricky. And the driver itself is located in `drivers/net/ethernet/meta/fbnic`, confirming my memory of its location. My immediate concerns are: can we *actually* reach and validate this new functionality? The patch fundamentally alters how we interpret firmware messages and introduces new read functions: `fbnic_hwmon_read`, `fbnic_hwmon_temp_read`, `fbnic_hwmon_in_read`. Plus, there’s this `fbnic_hwmon_notify_event` which is called from the threshold parser. This could be where the rubber hits the road in terms of triggering alarms, or at least that's where I need to look. Now, a critical question: is `fbnic` even *accessible* in virtualized environments? We're talking about a PCI driver, specifically for Meta's Host Network Interface. So, it's a PCI device. I wonder if we can fuzz this easily. Syzkaller is a powerful tool, but network drivers are usually tested via netlink or socket interfaces. The ideal scenario would be a dedicated syzkaller description for `fbnic`, but, is there a way to fuzz PCI devices through syzkaller if they are emulated or with vhci/PCI fuzzing? Wait, syzkaller has a PCI fuzzer! I'll have to investigate that. Finally, before I get lost in the weeds of fuzzing, I should make sure the driver is even enabled in a typical configuration. I'll need to search for `CONFIG_FBNIC` and determine if it's already part of the default builds or if we'll have to enable it specifically. |
| 4/2 | 2026/07/22 15:27 | tool | grepper |
0mError:no matches Args: {
"Expression": "config FBNIC",
"PathPrefix": "drivers/net/ethernet/meta/fbnic"
}Results: {
"error": "no matches"
} |
| 5/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10763 output: 35 thoughts: 19 Thoughts: Here's my take on the thought process, as if I were the one thinking it: **Diving into the Ethernet Kconfig** Alright, time to get my hands dirty. I'm going to start by taking a look at `drivers/net/ethernet/meta/Kconfig`. This is where the core configuration options for the Ethernet driver family should be defined. I'm expecting to see the broad, top-level settings, perhaps options for enabling or disabling the entire subsystem, and probably the inclusion of other, more specific Kconfig files for individual Ethernet controllers or features. I'll need to understand the hierarchy and dependencies laid out here – how different controller types are selected, how common features are enabled, and what the overall structure of the Ethernet configuration space looks like. I'll be looking for any potential conflicts, redundancies, or areas where I can potentially streamline the configuration process. Ultimately, I want a solid mental model of how this whole Ethernet configuration framework is put together. Let's see what we've got. |
| 6/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "config FBNIC",
"PathPrefix": "drivers/net/ethernet/meta/Kconfig"
}Results: {
"Output": "drivers/net/ethernet/meta/Kconfig=18=if NET_VENDOR_META\ndrivers/net/ethernet/meta/Kconfig-19-\ndrivers/net/ethernet/meta/Kconfig:20:config FBNIC\ndrivers/net/ethernet/meta/Kconfig-21-\ttristate \"Meta Platforms Host Network Interface\"\n"
} |
| 7/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11129 output: 44 thoughts: 119 Thoughts: **Analyzing the fbnic Driver Vulnerability** Okay, so I'm looking at `CONFIG_FBNIC`, that's my starting point. The new patch introduces `fbnic_hwmon_notify_event`, and I see it's called from `fbnic_fw_parse_threshold_exceeded_resp`. Right, that parser is definitely triggered by firmware messages. My immediate thought is, can Syzkaller trigger those firmware messages? If Syzkaller is fuzzing PCI, it has the potential to inject arbitrary responses to DMA/MMIO reads, which could be misinterpreted as valid firmware messages. It's plausible. Now, I need to understand the call path to `fbnic_fw_parse_threshold_exceeded_resp` itself and confirm that Syzkaller can, in fact, provide the necessary inputs. I need to trace back from that function and see how it's invoked. Let's dig deeper and see. |
| 8/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "fbnic_fw_parse_threshold_exceeded_resp",
"PathPrefix": "drivers/net/ethernet/meta/fbnic"
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_fw.c=1642=static const struct fbnic_tlv_index fbnic_threshold_exceeded_resp_index[] = {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1649-\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:1650:static int fbnic_fw_parse_threshold_exceeded_resp(void *opaque,\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1651-\t\t\t\t\t\t struct fbnic_tlv_msg **results)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c=1693=static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1722-\t\t\t fbnic_threshold_exceeded_resp_index,\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:1723:\t\t\t fbnic_fw_parse_threshold_exceeded_resp),\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1724-\tFBNIC_TLV_PARSER(LOG_MSG_REQ,\n"
} |
| 9/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11833 output: 40 thoughts: 36 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Investigating the `fbnic_fw_tlv_parser` Usage** Alright, I'm diving into the `fbnic_fw_tlv_parser` module, recognizing it's responsible for parsing a specific data format. Now, my immediate thought is to understand its scope and impact within the larger system. I need to get a clear picture of *where* this parser is being utilized. Essentially, I want to trace its call graph and dependency tree. Understanding its consumers is crucial. Are we talking about a central component, or something more localized? Identifying every instance of `fbnic_fw_tlv_parser` in use is the first, essential step. I'll need to use my usual tools to perform this cross-referencing, probably a grep or a similar function call. From there, I can begin to assess its role and potential vulnerabilities, or areas ripe for optimization. This will inform my next steps, whatever they may be. |
| 10/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "fbnic_fw_tlv_parser",
"PathPrefix": "drivers/net/ethernet/meta/fbnic"
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_fw.c=1650=static int fbnic_fw_parse_threshold_exceeded_resp(void *opaque,\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1692-\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:1693:static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1694-\tFBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, fbnic_fw_parser_test),\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c=1730=static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1766-\t\t/* If parsing fails dump contents of message to dmesg */\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:1767:\t\terr = fbnic_tlv_msg_parse(fbd, msg, fbnic_fw_tlv_parser);\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1768-\t\tif (err) {\n"
} |
| 11/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12492 output: 46 thoughts: 365 Thoughts: **My Analysis of the FBNIC Patch's Fuzzing Surface** Okay, so I'm looking at this patch and immediately, I see a few key areas that are likely to be vulnerable and, more importantly, fuzzable. This is related to the `fbnic` driver, specifically its interaction with the mailbox, and the hardware monitoring (hwmon) aspects. First, I see this is used in `fbnic_mbx_process_rx_msgs`. That function is crucial because it processes messages coming *from* the hardware. The mailbox itself is likely populated through direct memory access (DMA) or memory-mapped I/O (MMIO), which means we're dealing with potentially untrusted data flowing from the device to the kernel. This is a classic target for fuzzing, and I know Syzkaller's PCI fuzzer is particularly well-suited to poking at these kinds of interfaces. Then I note the changes to the hwmon functions. The patch modifies `fbnic_hwmon_read` and *adds* `fbnic_hwmon_temp_read` and `fbnic_hwmon_in_read`. Those are all accessed through the sysfs interface. I know Syzkaller is quite adept at interacting with sysfs files, so it can be used to trigger these functions easily. That `fbnic_hwmon_read` function could be the entry point to a lot of interesting logic. Now, let's look at the configuration requirements. To enable this area, I need `CONFIG_FBNIC`, obviously. Also, `CONFIG_HWMON` is necessary because `fbnic_hwmon_register` checks `IS_REACHABLE(CONFIG_HWMON)`. Interestingly, even though `fbnic_hwmon_register` is compiled unconditionally, it *checks* `HWMON` via a conditional return! So, I need `HWMON` enabled to make sure the relevant code path is active. Now to define the attack surface. From the code, the functions I need to focus on for fuzzing purposes are: * `fbnic_fw_parse_threshold_exceeded_resp` (likely firmware parsing, interesting for crafted messages) * `fbnic_hwmon_temp_read`, `fbnic_hwmon_in_read`, `fbnic_hwmon_sensor_read`, and `fbnic_hwmon_notify_event` (these seem like low-hanging fruit, they read values from hwmon interface) * `fbnic_hwmon_read` (the potentially important function, and I'll need to check which file it's in to ensure it aligns with my assessment) Finally, I need to confirm `fbnic_hwmon_read` is indeed in `fbnic_hwmon.c` so I'm on the right track. |
| 12/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "fbnic_hwmon_read",
"PathPrefix": "drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c"
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c=17=static int fbnic_hwmon_sensor_read(struct fbnic_dev *fbd, int id, long *val)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-80-\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:81:static int fbnic_hwmon_read_threshold(long thr, long *val)\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-82-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-89-\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:90:static int fbnic_hwmon_read_alarm(long a, long b, long *val)\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-91-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c=99=static int fbnic_hwmon_temp_read(struct fbnic_dev *fbd, u32 attr, long *val)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-104-\tcase hwmon_temp_min:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:105:\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.temp.min, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-106-\tcase hwmon_temp_max:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:107:\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.temp.max, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-108-\tcase hwmon_temp_crit:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:109:\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.temp.crit, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-110-\tcase hwmon_temp_input:\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-126-\tcase hwmon_temp_min_alarm:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:127:\t\treturn fbnic_hwmon_read_alarm(fbd-\u003efw_cap.temp.min, *val, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-128-\tcase hwmon_temp_max_alarm:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:129:\t\treturn fbnic_hwmon_read_alarm(*val, fbd-\u003efw_cap.temp.max, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-130-\tcase hwmon_temp_crit_alarm:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:131:\t\treturn fbnic_hwmon_read_alarm(*val, fbd-\u003efw_cap.temp.crit, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-132-\t}\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c=137=static int fbnic_hwmon_in_read(struct fbnic_dev *fbd, u32 attr, long *val)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-142-\tcase hwmon_in_min:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:143:\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.volt.min, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-144-\tcase hwmon_in_max:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:145:\t\treturn fbnic_hwmon_read_threshold(fbd-\u003efw_cap.volt.max, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-146-\tcase hwmon_in_input:\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-161-\tcase hwmon_in_min_alarm:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:162:\t\treturn fbnic_hwmon_read_alarm(fbd-\u003efw_cap.volt.min, *val, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-163-\tcase hwmon_in_max_alarm:\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:164:\t\treturn fbnic_hwmon_read_alarm(*val, fbd-\u003efw_cap.volt.max, val);\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-165-\t}\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-169-\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:170:static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-171-\t\t\t u32 attr, int channel, long *val)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c=185=static const struct hwmon_ops fbnic_hwmon_ops = {\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-186-\t.is_visible = fbnic_hwmon_is_visible,\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:187:\t.read = fbnic_hwmon_read,\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c-188-};\n"
} |
| 13/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15135 output: 35 thoughts: 163 Thoughts: **Analyzing the FBNIC Hardware Monitoring Code** Okay, so I'm looking at these functions: `fbnic_fw_parse_threshold_exceeded_resp`, `fbnic_hwmon_temp_read`, `fbnic_hwmon_in_read`, `fbnic_hwmon_sensor_read`, `fbnic_hwmon_notify_event`, and `fbnic_hwmon_read`. These are clearly part of the FBNIC hardware monitoring infrastructure, likely dealing with temperature, voltage, and potentially other sensor data related to the FBNIC network interface card. My immediate question is about the configuration options. I need to know if `CONFIG_FBNIC` is defined. Ah, yes, it's a tristate, so `FBNIC` is the symbol used in the kernel config. Right, so `fbnic_hwmon_register` is defined in `fbnic_hwmon.c`. Let me take a quick look to see if there are any other configuration dependencies in the Kconfig files. Time to check `drivers/net/ethernet/meta/Kconfig` again. |
| 14/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "config FBNIC",
"PathPrefix": "drivers/net/ethernet/meta/Kconfig"
}Results: {
"Output": "drivers/net/ethernet/meta/Kconfig=18=if NET_VENDOR_META\ndrivers/net/ethernet/meta/Kconfig-19-\ndrivers/net/ethernet/meta/Kconfig:20:config FBNIC\ndrivers/net/ethernet/meta/Kconfig-21-\ttristate \"Meta Platforms Host Network Interface\"\n"
} |
| 15/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15672 output: 37 thoughts: 27 Thoughts: Here's my thought process, as it stands: **Checking on Network Vendor Metadata** Okay, so I'm putting together this overview and realized I glossed over something potentially important. I've got `NET_VENDOR_META` in my notes, but I need to make absolutely sure it's handled correctly. It's too easy to miss these little dependencies. Right now, I need to verify that `NET_VENDOR_META` is either enabled by default in the relevant configurations, or else clearly note what's required to enable it within the scope of the project. I'll need to go through the current settings and see what the status is. That's the priority now. |
| 16/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "config NET_VENDOR_META",
"PathPrefix": "drivers/net/ethernet/meta/Kconfig"
}Results: {
"Output": "drivers/net/ethernet/meta/Kconfig-5-\ndrivers/net/ethernet/meta/Kconfig:6:config NET_VENDOR_META\ndrivers/net/ethernet/meta/Kconfig-7-\tbool \"Meta Platforms devices\"\n"
} |
| 17/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15953 output: 48 thoughts: 373 Thoughts: **My Assessment of the FBNIC Driver Configuration and Vulnerability Surface** Okay, so I've got the configuration context here. It looks like `NET_VENDOR_META`, `FBNIC`, and `HWMON` are the key configurations to enable. So my immediate thought is to build a configuration array like: `["NET_VENDOR_META", "FBNIC", "HWMON"]`. That sets the stage. Now, I need to understand the attack surface. My initial focus is on the `fbnic_hwmon` interactions because of their potential for direct hardware access. I'm zeroing in on `fbnic_hwmon_sensor_read` to see if it's reachable. It appears it is, indirectly, through a chain: `fbnic_hwmon_temp_read`, `fbnic_hwmon_in_read`, and `fbnic_hwmon_read`, which is registered as the `hwmon_ops.read` function, meaning it's reachable through sysfs reads on the hwmon device. This is a good sign for fuzzing, and a likely avenue for exploitation. On a different vector, I have the `fbnic_fw_parse_threshold_exceeded_resp` function, which is reachable via firmware messages, or mailbox. This also seems to be a solid target for fuzzing. It's clearly functional. My current focus symbols are: * `fbnic_fw_parse_threshold_exceeded_resp` (firmware mailbox) * `fbnic_hwmon_temp_read` * `fbnic_hwmon_in_read` * `fbnic_hwmon_sensor_read` (reachable via `hwmon` device) * `fbnic_hwmon_notify_event` * `fbnic_hwmon_read` Next, I need to check `fbnic_hwmon_sensor_read` to see if it is a static function. Yes, it is. Then let's verify if `fbnic_hwmon_notify_event` is exported or just global. It is global in `fbnic_hwmon.c` and called from `fbnic_fw.c`, which makes it a good symbol to focus on. Finally, I need to see what else has been modified. It looks like `fbnic_fw_parse_cap_resp` was modified to parse threshold values. This now appears to be another solid focus symbol and an extension of the firmware messaging vector. |
| 18/2 | 2026/07/22 15:27 | tool | grepper |
0mArgs:{
"Expression": "fbnic_fw_parse_cap_resp",
"PathPrefix": "drivers/net/ethernet/meta/fbnic/fbnic_fw.c"
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_fw.c=586=static int fbnic_fw_parse_bmc_addrs(u8 bmc_mac_addr[][ETH_ALEN],\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-614-\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:615:static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-616-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c=1693=static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1695-\tFBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index,\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:1696:\t\t\t fbnic_fw_parse_cap_resp),\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c-1697-\tFBNIC_TLV_PARSER(OWNERSHIP_RESP, fbnic_ownership_resp_index,\n"
} |
| 19/2 | 2026/07/22 15:27 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17274 output: 233 thoughts: 284 Thoughts: **My Assessment of the fbnic Driver Modifications** Okay, so I see that `fbnic_fw_parse_cap_resp` has been modified, which is a key starting point. I'll need to investigate that change thoroughly, especially given that this is likely related to the new functionality. Next, I need to look into `fbnic_hwmon_read_threshold` and `fbnic_hwmon_read_alarm`. They're static helpers within `fbnic_hwmon.c`, so they're definitely candidates for inclusion in my FocusSymbols list. They would be perfect to fuzz. Let me summarize the scope: my FocusSymbols will be: * `fbnic_fw_parse_threshold_exceeded_resp` (the firmware response parser) * `fbnic_fw_parse_cap_resp` (the modified capability response) * `fbnic_hwmon_temp_read` (temperature sensor reading) * `fbnic_hwmon_in_read` (voltage sensor reading) * `fbnic_hwmon_sensor_read` (generic sensor read) * `fbnic_hwmon_notify_event` (event notification) * `fbnic_hwmon_read` (general hwmon read) * `fbnic_hwmon_read_threshold` (threshold reading - a static helper) * `fbnic_hwmon_read_alarm` (alarm reading - also a static helper) The underlying reasoning here is that this patch introduces significant changes to the fbnic driver's hardware monitoring capabilities, including reading from new sysfs interfaces for temperature and voltage, and parsing firmware messages related to threshold exceedance. These functions are prime targets. I can fuzz this by writing to sysfs and emulating PCI/mailbox interactions. Those FocusSymbols are my attack surface. Let's call `set-results`. |
| 20/2 | 2026/07/22 15:27 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"NET_VENDOR_META",
"FBNIC",
"HWMON"
],
"FocusSymbols": [
"fbnic_fw_parse_threshold_exceeded_resp",
"fbnic_fw_parse_cap_resp",
"fbnic_hwmon_temp_read",
"fbnic_hwmon_in_read",
"fbnic_hwmon_sensor_read",
"fbnic_hwmon_notify_event",
"fbnic_hwmon_read",
"fbnic_hwmon_read_threshold",
"fbnic_hwmon_read_alarm"
],
"Reasoning": "The patch adds hardware monitoring threshold and alarm support to the fbnic driver. It introduces new sysfs read handlers for temperature and voltage sensors, and adds a firmware message parser for threshold exceeded events. These are functional changes to the driver's hwmon interface and firmware mailbox processing, which can be fuzzed via sysfs and emulated PCI/mailbox interactions.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"NET_VENDOR_META",
"FBNIC",
"HWMON"
],
"FocusSymbols": [
"fbnic_fw_parse_threshold_exceeded_resp",
"fbnic_fw_parse_cap_resp",
"fbnic_hwmon_temp_read",
"fbnic_hwmon_in_read",
"fbnic_hwmon_sensor_read",
"fbnic_hwmon_notify_event",
"fbnic_hwmon_read",
"fbnic_hwmon_read_threshold",
"fbnic_hwmon_read_alarm"
],
"Reasoning": "The patch adds hardware monitoring threshold and alarm support to the fbnic driver. It introduces new sysfs read handlers for temperature and voltage sensors, and adds a firmware message parser for threshold exceeded events. These are functional changes to the driver's hwmon interface and firmware mailbox processing, which can be fuzzed via sysfs and emulated PCI/mailbox interactions.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|