| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/10/15 03:24 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the fbnic driver (drivers/net/ethernet/meta/fbnic/), which supports Meta's custom PCIe Host Network Interface ASIC. This driver requires physical PCIe hardware not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
} |
| 1/1 | 2026/10/15 03:24 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 7fd4afac6287f4827bd1734f116b90839d3cdf3f\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Oct 15 03:24:41 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 1f9fbd71447f9..8180028b20a20 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic.h\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h\n@@ -22,11 +22,20 @@ 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+\tu8 temp_alarm;\n+\tu8 volt_alarm;\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@@ -191,6 +200,8 @@ 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);\n+void fbnic_hwmon_old_notify_event(struct fbnic_dev *fbd, int id, s32 value);\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 49b8813a35643..cfec30e5cb988 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c\n@@ -95,15 +95,34 @@ static void fbnic_mbx_reset_desc_ring(struct fbnic_dev *fbd, int mbx_idx)\n \t\t\t\t\t FBNIC_IPC_MBX_DESC_HOST_CMPL);\n }\n \n+static const struct fbnic_threshold fbnic_threshold_no_data = {\n+\t.min\t= FBNIC_SENSOR_NO_DATA,\n+\t.max\t= FBNIC_SENSOR_NO_DATA,\n+\t.crit\t= FBNIC_SENSOR_NO_DATA,\n+};\n+\n void fbnic_mbx_init(struct fbnic_dev *fbd)\n {\n+\tstruct fbnic_fw_cap fw_cap_reset;\n \tint i;\n \n \t/* Initialize lock to protect Tx ring */\n \tspin_lock_init(\u0026fbd-\u003efw_tx_lock);\n \n-\t/* Reset FW Capabilities */\n-\tmemset(\u0026fbd-\u003efw_cap, 0, sizeof(fbd-\u003efw_cap));\n+\t/* Reset FW Capabilities and seed thresholds with sentinel */\n+\tmemset(\u0026fw_cap_reset, 0, sizeof(fw_cap_reset));\n+\tfw_cap_reset.temp = fbnic_threshold_no_data;\n+\tfw_cap_reset.volt = fbnic_threshold_no_data;\n+\tfbd-\u003efw_cap = fw_cap_reset;\n+\n+\t/* Seed cache with sentinel so the first read always refreshes. The\n+\t * cache mirrors what firmware reported, so drop it when the mailbox\n+\t * restarts.\n+\t */\n+\tfbd-\u003ehwmon_cache.temp_mdeg = FBNIC_SENSOR_NO_DATA;\n+\tfbd-\u003ehwmon_cache.volt_mv = FBNIC_SENSOR_NO_DATA;\n+\tfbd-\u003ehwmon_cache.temp_alarm = FBNIC_FW_TSENE_ALARM_UNKNOWN;\n+\tfbd-\u003ehwmon_cache.volt_alarm = FBNIC_FW_TSENE_ALARM_UNKNOWN;\n \n \t/* Reinitialize mailbox memory */\n \tfor (i = 0; i \u003c FBNIC_IPC_MBX_INDICES; i++)\n@@ -588,6 +607,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@@ -735,6 +759,22 @@ static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)\n \tfbd-\u003efw_cap.anti_rollback_version =\n \t\tfta_get_uint(results, FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION);\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@@ -1428,6 +1468,8 @@ static const struct fbnic_tlv_index fbnic_tsene_read_resp_index[] = {\n \tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERM),\n \tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLT),\n \tFBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_ERROR),\n+\tFBNIC_TLV_ATTR_U32(FBNIC_FW_TSENE_THERM_ALARM_STATE),\n+\tFBNIC_TLV_ATTR_U32(FBNIC_FW_TSENE_VOLT_ALARM_STATE),\n \tFBNIC_TLV_ATTR_LAST\n };\n \n@@ -1438,6 +1480,7 @@ static int fbnic_fw_parse_tsene_read_resp(void *opaque,\n \tstruct fbnic_dev *fbd = opaque;\n \ts32 err_resp;\n \tint err = 0;\n+\tu32 alarm;\n \n \t/* Verify we have a completion pointer to provide with data */\n \tcmpl_data = fbnic_fw_get_cmpl_by_type(fbd,\n@@ -1459,6 +1502,20 @@ static int fbnic_fw_parse_tsene_read_resp(void *opaque,\n \tcmpl_data-\u003eu.tsene.millivolts =\n \t\tfta_get_sint(results, FBNIC_FW_TSENE_VOLT);\n \n+\t/* Cache here so that it and the threshold event land in the order firmware\n+\t * sent them. Firmware predating alarm state reporting sends neither\n+\t * attribute.\n+\t */\n+\talarm = fbnic_tlv_attr_get_unsigned(results[FBNIC_FW_TSENE_THERM_ALARM_STATE],\n+\t\t\t\t\t FBNIC_FW_TSENE_ALARM_UNKNOWN);\n+\tif (alarm != FBNIC_FW_TSENE_ALARM_UNKNOWN)\n+\t\tWRITE_ONCE(fbd-\u003ehwmon_cache.temp_alarm, alarm);\n+\n+\talarm = fbnic_tlv_attr_get_unsigned(results[FBNIC_FW_TSENE_VOLT_ALARM_STATE],\n+\t\t\t\t\t FBNIC_FW_TSENE_ALARM_UNKNOWN);\n+\tif (alarm != FBNIC_FW_TSENE_ALARM_UNKNOWN)\n+\t\tWRITE_ONCE(fbd-\u003ehwmon_cache.volt_alarm, alarm);\n+\n msg_err:\n \tcmpl_data-\u003eresult = err_resp ? : err;\n \tcomplete(\u0026cmpl_data-\u003edone);\n@@ -1651,6 +1708,82 @@ 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_U32(FBNIC_FW_TSENE_THERM_ALARM),\n+\tFBNIC_TLV_ATTR_U32(FBNIC_FW_TSENE_VOLT_ALARM),\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\n+\t\t\t\t\t\t **results)\n+{\n+\tstruct fbnic_dev *fbd = opaque;\n+\tbool rec_flag = false;\n+\tu32 alarm;\n+\ts32 value;\n+\n+\tif (results[FBNIC_FW_TSENE_THERM_ALARM]) {\n+\t\tbool have_temp = !!results[FBNIC_FW_TSENE_THERMAL];\n+\n+\t\talarm = fta_get_uint(results, FBNIC_FW_TSENE_THERM_ALARM);\n+\t\tvalue = fta_get_sint(results, FBNIC_FW_TSENE_THERMAL);\n+\t\tif (!have_temp)\n+\t\t\tdev_err(fbd-\u003edev, \"Thermal alarm %u received with no temperature!\\n\",\n+\t\t\t\talarm);\n+\t\telse if (alarm != FBNIC_FW_TSENE_ALARM_NORMAL)\n+\t\t\tdev_err(fbd-\u003edev, \"Thermal alarm %u, temperature is currently %dmC!\\n\",\n+\t\t\t\talarm, value);\n+\n+\t\tif (alarm == FBNIC_FW_TSENE_ALARM_DEPRECATED) {\n+\t\t\t/* Nothing to derive the range from, so do not guess */\n+\t\t\tif (have_temp)\n+\t\t\t\tfbnic_hwmon_old_notify_event(fbd,\n+\t\t\t\t\t\t\t FBNIC_SENSOR_TEMP,\n+\t\t\t\t\t\t\t value);\n+\t\t} else {\n+\t\t\tWRITE_ONCE(fbd-\u003ehwmon_cache.temp_alarm, alarm);\n+\t\t\tfbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_TEMP);\n+\t\t}\n+\t\trec_flag = true;\n+\t}\n+\n+\tif (results[FBNIC_FW_TSENE_VOLT_ALARM]) {\n+\t\tbool have_volt = !!results[FBNIC_FW_TSENE_VOLTAGE];\n+\n+\t\talarm = fta_get_uint(results, FBNIC_FW_TSENE_VOLT_ALARM);\n+\t\tvalue = fta_get_sint(results, FBNIC_FW_TSENE_VOLTAGE);\n+\t\tif (!have_volt)\n+\t\t\tdev_err(fbd-\u003edev, \"Voltage alarm %u received with no voltage!\\n\",\n+\t\t\t\talarm);\n+\t\telse if (alarm != FBNIC_FW_TSENE_ALARM_NORMAL)\n+\t\t\tdev_err(fbd-\u003edev, \"Voltage alarm %u, voltage is currently %dmV!\\n\",\n+\t\t\t\talarm, value);\n+\n+\t\tif (alarm == FBNIC_FW_TSENE_ALARM_DEPRECATED) {\n+\t\t\t/* Nothing to derive the range from, so do not guess */\n+\t\t\tif (have_volt)\n+\t\t\t\tfbnic_hwmon_old_notify_event(fbd,\n+\t\t\t\t\t\t\t FBNIC_SENSOR_VOLTAGE,\n+\t\t\t\t\t\t\t value);\n+\t\t} else {\n+\t\t\tWRITE_ONCE(fbd-\u003ehwmon_cache.volt_alarm, alarm);\n+\t\t\tfbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_VOLTAGE);\n+\t\t}\n+\t\trec_flag = true;\n+\t}\n+\n+\tif (!rec_flag) {\n+\t\tdev_warn(fbd-\u003edev,\n+\t\t\t \"Threshold exceeded message received but no alarm found!\\n\");\n+\t\treturn -EINVAL;\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@@ -1679,6 +1812,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 f47669129c9de..3b47872774088 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@@ -59,6 +60,18 @@ enum {\n \t(BIT(FBNIC_FW_CAP_F_BMC_TCAM_REINIT) |\t\\\n \t BIT(FBNIC_FW_CAP_F_BMC_MACDA_SYNC))\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 \tunsigned long state;\n \tstruct {\n@@ -72,6 +85,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@@ -224,6 +239,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@@ -254,6 +270,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@@ -284,9 +306,31 @@ enum {\n \tFBNIC_FW_TSENE_THERM\t\t\t= 0x0,\n \tFBNIC_FW_TSENE_VOLT\t\t\t= 0x1,\n \tFBNIC_FW_TSENE_ERROR\t\t\t= 0x2,\n+\tFBNIC_FW_TSENE_THERM_ALARM_STATE\t= 0x3,\n+\tFBNIC_FW_TSENE_VOLT_ALARM_STATE\t\t= 0x4,\n \tFBNIC_FW_TSENE_MSG_MAX\n };\n \n+enum {\n+\tFBNIC_FW_TSENE_THERM_ALARM\t\t= 0x0,\n+\tFBNIC_FW_TSENE_VOLT_ALARM\t\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_TSENE_ALARM_NORMAL\t\t= 0x0,\n+\tFBNIC_FW_TSENE_ALARM_DEPRECATED\t\t= 0x1,\n+\tFBNIC_FW_TSENE_ALARM_BELOW_MIN\t\t= 0x2,\n+\tFBNIC_FW_TSENE_ALARM_ABOVE_MAX\t\t= 0x3,\n+\tFBNIC_FW_TSENE_ALARM_CRIT\t\t= 0x4,\n+\t/* Driver internal, never sent by firmware. 0xff so its out of\n+\t * range wherever the range is held in a u8.\n+\t */\n+\tFBNIC_FW_TSENE_ALARM_UNKNOWN\t\t= 0xff,\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 def8598aceecf..9fa9eb843c689 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,246 @@\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_thr_visible(s32 thr)\n {\n-\tif (type == hwmon_temp)\n-\t\treturn FBNIC_SENSOR_TEMP;\n-\tif (type == hwmon_in)\n-\t\treturn FBNIC_SENSOR_VOLTAGE;\n-\n-\treturn -EOPNOTSUPP;\n+\treturn thr == FBNIC_SENSOR_NO_DATA ? 0 : 0444;\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 {\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+\tconst struct fbnic_dev *fbd = drvdata;\n+\n+\tswitch (type) {\n+\tcase hwmon_temp:\n+\t\tswitch (attr) {\n+\t\tcase hwmon_temp_input:\n+\t\t\treturn 0444;\n+\t\tcase hwmon_temp_min:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.temp.min);\n+\t\tcase hwmon_temp_max:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.temp.max);\n+\t\tcase hwmon_temp_crit:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.temp.crit);\n+\t\tcase hwmon_temp_alarm:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.temp.min) \u0026\n+\t\t\t fbnic_hwmon_thr_visible(fbd-\u003efw_cap.temp.max) \u0026\n+\t\t\t fbnic_hwmon_thr_visible(fbd-\u003efw_cap.temp.crit);\n+\t\t}\n+\t\tbreak;\n+\tcase hwmon_in:\n+\t\tswitch (attr) {\n+\t\tcase hwmon_in_input:\n+\t\t\treturn 0444;\n+\t\tcase hwmon_in_min:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.volt.min);\n+\t\tcase hwmon_in_max:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.volt.max);\n+\t\tcase hwmon_in_alarm:\n+\t\t\treturn fbnic_hwmon_thr_visible(fbd-\u003efw_cap.volt.min) \u0026\n+\t\t\t fbnic_hwmon_thr_visible(fbd-\u003efw_cap.volt.max);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\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 cache-\u003elast_read == jiffies) {\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 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 bool fbnic_hwmon_at_or_above(long val, s32 thr)\n+{\n+\treturn thr != FBNIC_SENSOR_NO_DATA \u0026\u0026 val \u003e= thr;\n+}\n+\n+static bool fbnic_hwmon_below(long val, s32 thr)\n+{\n+\treturn thr != FBNIC_SENSOR_NO_DATA \u0026\u0026 val \u003c thr;\n+}\n+\n+static u8 fbnic_hwmon_classify(const struct fbnic_threshold *thr, long val)\n+{\n+\tif (fbnic_hwmon_at_or_above(val, thr-\u003ecrit))\n+\t\treturn FBNIC_FW_TSENE_ALARM_CRIT;\n+\tif (fbnic_hwmon_at_or_above(val, thr-\u003emax))\n+\t\treturn FBNIC_FW_TSENE_ALARM_ABOVE_MAX;\n+\tif (fbnic_hwmon_below(val, thr-\u003emin))\n+\t\treturn FBNIC_FW_TSENE_ALARM_BELOW_MIN;\n+\n+\treturn FBNIC_FW_TSENE_ALARM_NORMAL;\n+}\n+\n+static int fbnic_hwmon_alarm_read(struct fbnic_dev *fbd,\n+\t\t\t\t enum hwmon_sensor_types type, long *val)\n+{\n+\tstruct fbnic_hwmon_cache *cache = \u0026fbd-\u003ehwmon_cache;\n+\tconst struct fbnic_threshold *thr;\n+\tu8 *cached, alarm;\n+\tlong reading;\n+\tint id, err;\n+\n+\tswitch (type) {\n+\tcase hwmon_temp:\n+\t\tthr = \u0026fbd-\u003efw_cap.temp;\n+\t\tcached = \u0026cache-\u003etemp_alarm;\n+\t\tid = FBNIC_SENSOR_TEMP;\n+\t\tbreak;\n+\tcase hwmon_in:\n+\t\tthr = \u0026fbd-\u003efw_cap.volt;\n+\t\tcached = \u0026cache-\u003evolt_alarm;\n+\t\tid = FBNIC_SENSOR_VOLTAGE;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\t/* Paired with WRITE_ONCE() on the mailbox thread. Firmware only\n+\t * reports on a threshold crossing, so nothing is cached until the\n+\t * first one. Read the sensor, whose response carries the range.\n+\t */\n+\talarm = READ_ONCE(*cached);\n+\tif (alarm == FBNIC_FW_TSENE_ALARM_UNKNOWN) {\n+\t\terr = fbnic_hwmon_sensor_read(fbd, id, \u0026reading);\n+\t\tif (err)\n+\t\t\treturn err;\n+\n+\t\talarm = READ_ONCE(*cached);\n+\n+\t\t/* Firmware too old to report a range, derive it instead */\n+\t\tif (alarm == FBNIC_FW_TSENE_ALARM_UNKNOWN)\n+\t\t\talarm = fbnic_hwmon_classify(thr, reading);\n+\t}\n+\n+\t*val = alarm != FBNIC_FW_TSENE_ALARM_NORMAL;\n \n \treturn 0;\n }\n \n+static int fbnic_hwmon_temp_read(struct fbnic_dev *fbd, u32 attr, long *val)\n+{\n+\tswitch (attr) {\n+\tcase hwmon_temp_input:\n+\t\treturn fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_TEMP, val);\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_alarm:\n+\t\treturn fbnic_hwmon_alarm_read(fbd, hwmon_temp, val);\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n+static int fbnic_hwmon_in_read(struct fbnic_dev *fbd, u32 attr, long *val)\n+{\n+\tswitch (attr) {\n+\tcase hwmon_in_input:\n+\t\treturn fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_VOLTAGE, val);\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_alarm:\n+\t\treturn fbnic_hwmon_alarm_read(fbd, hwmon_in, val);\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\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 +250,12 @@ 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 | HWMON_T_ALARM |\n+\t\t\t HWMON_T_MIN | HWMON_T_MAX | HWMON_T_CRIT),\n+\tHWMON_CHANNEL_INFO(in,\n+\t\t\t HWMON_I_INPUT | HWMON_I_ALARM |\n+\t\t\t HWMON_I_MIN | HWMON_I_MAX),\n \tNULL\n };\n \n@@ -57,25 +266,98 @@ 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+\thwmon = hwmon_device_register_with_info(fbd-\u003edev, \"fbnic\",\n+\t\t\t\t\t\tfbd, \u0026fbnic_chip_info,\n+\t\t\t\t\t\tNULL);\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_old_notify_event(struct fbnic_dev *fbd, int id, s32 value)\n+{\n+\tconst struct fbnic_threshold *thr;\n+\tu8 *cached;\n+\n+\tswitch (id) {\n+\tcase FBNIC_SENSOR_TEMP:\n+\t\tthr = \u0026fbd-\u003efw_cap.temp;\n+\t\tcached = \u0026fbd-\u003ehwmon_cache.temp_alarm;\n+\t\tbreak;\n+\tcase FBNIC_SENSOR_VOLTAGE:\n+\t\tthr = \u0026fbd-\u003efw_cap.volt;\n+\t\tcached = \u0026fbd-\u003ehwmon_cache.volt_alarm;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn;\n+\t}\n+\n+\t/* Event arrived before the capability response containing\n+\t * the thresholds.\n+\t */\n+\tif (thr-\u003emin == FBNIC_SENSOR_NO_DATA ||\n+\t thr-\u003emax == FBNIC_SENSOR_NO_DATA)\n+\t\treturn;\n+\n+\tWRITE_ONCE(*cached, fbnic_hwmon_classify(thr, value));\n+\tfbnic_hwmon_notify_event(fbd, id);\n+}\n+\n+void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id)\n+{\n+\tenum hwmon_sensor_types type;\n+\tstruct device *hwmon;\n+\tu32 attr;\n+\n+\tif (!IS_REACHABLE(CONFIG_HWMON))\n+\t\treturn;\n+\n+\tswitch (id) {\n+\tcase FBNIC_SENSOR_TEMP:\n+\t\ttype = hwmon_temp;\n+\t\tattr = hwmon_temp_alarm;\n+\t\tbreak;\n+\tcase FBNIC_SENSOR_VOLTAGE:\n+\t\ttype = hwmon_in;\n+\t\tattr = hwmon_in_alarm;\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 (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 16271c717a5aa..3e1256ffd1411 100644\n--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c\n+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c\n@@ -892,60 +892,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@@ -959,7 +905,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 10f30e0e8f691..bde2daa656457 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/10/15 03:24 | agent | patch-evaluator |
1mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the fbnic driver (drivers/net/ethernet/meta/fbnic/), which supports Meta's custom PCIe Host Network Interface ASIC. This driver requires physical PCIe hardware not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any '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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 7fd4afac6287f4827bd1734f116b90839d3cdf3f
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Oct 15 03:24:41 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 1f9fbd71447f9..8180028b20a20 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h
@@ -22,11 +22,20 @@ 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;
+ u8 temp_alarm;
+ u8 volt_alarm;
+};
+
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;
@@ -191,6 +200,8 @@ 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);
+void fbnic_hwmon_old_notify_event(struct fbnic_dev *fbd, int id, s32 value);
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 49b8813a35643..cfec30e5cb988 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
@@ -95,15 +95,34 @@ static void fbnic_mbx_reset_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
FBNIC_IPC_MBX_DESC_HOST_CMPL);
}
+static const struct fbnic_threshold fbnic_threshold_no_data = {
+ .min = FBNIC_SENSOR_NO_DATA,
+ .max = FBNIC_SENSOR_NO_DATA,
+ .crit = FBNIC_SENSOR_NO_DATA,
+};
+
void fbnic_mbx_init(struct fbnic_dev *fbd)
{
+ struct fbnic_fw_cap fw_cap_reset;
int i;
/* Initialize lock to protect Tx ring */
spin_lock_init(&fbd->fw_tx_lock);
- /* Reset FW Capabilities */
- memset(&fbd->fw_cap, 0, sizeof(fbd->fw_cap));
+ /* Reset FW Capabilities and seed thresholds with sentinel */
+ memset(&fw_cap_reset, 0, sizeof(fw_cap_reset));
+ fw_cap_reset.temp = fbnic_threshold_no_data;
+ fw_cap_reset.volt = fbnic_threshold_no_data;
+ fbd->fw_cap = fw_cap_reset;
+
+ /* Seed cache with sentinel so the first read always refreshes. The
+ * cache mirrors what firmware reported, so drop it when the mailbox
+ * restarts.
+ */
+ fbd->hwmon_cache.temp_mdeg = FBNIC_SENSOR_NO_DATA;
+ fbd->hwmon_cache.volt_mv = FBNIC_SENSOR_NO_DATA;
+ fbd->hwmon_cache.temp_alarm = FBNIC_FW_TSENE_ALARM_UNKNOWN;
+ fbd->hwmon_cache.volt_alarm = FBNIC_FW_TSENE_ALARM_UNKNOWN;
/* Reinitialize mailbox memory */
for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
@@ -588,6 +607,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
};
@@ -735,6 +759,22 @@ static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)
fbd->fw_cap.anti_rollback_version =
fta_get_uint(results, FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION);
+ 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;
}
@@ -1428,6 +1468,8 @@ static const struct fbnic_tlv_index fbnic_tsene_read_resp_index[] = {
FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERM),
FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLT),
FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_ERROR),
+ FBNIC_TLV_ATTR_U32(FBNIC_FW_TSENE_THERM_ALARM_STATE),
+ FBNIC_TLV_ATTR_U32(FBNIC_FW_TSENE_VOLT_ALARM_STATE),
FBNIC_TLV_ATTR_LAST
};
@@ -1438,6 +1480,7 @@ static int fbnic_fw_parse_tsene_read_resp(void *opaque,
struct fbnic_dev *fbd = opaque;
s32 err_resp;
int err = 0;
+ u32 alarm;
/* Verify we have a completion pointer to provide with data */
cmpl_data = fbnic_fw_get_cmpl_by_type(fbd,
@@ -1459,6 +1502,20 @@ static int fbnic_fw_parse_tsene_read_resp(void *opaque,
cmpl_data->u.tsene.millivolts =
fta_get_sint(results, FBNIC_FW_TSENE_VOLT);
+ /* Cache here so that it and the threshold event land in the order firmware
+ * sent them. Firmware predating alarm state reporting sends neither
+ * attribute.
+ */
+ alarm = fbnic_tlv_attr_get_unsigned(results[FBNIC_FW_TSENE_THERM_ALARM_STATE],
+ FBNIC_FW_TSENE_ALARM_UNKNOWN);
+ if (alarm != FBNIC_FW_TSENE_ALARM_UNKNOWN)
+ WRITE_ONCE(fbd->hwmon_cache.temp_alarm, alarm);
+
+ alarm = fbnic_tlv_attr_get_unsigned(results[FBNIC_FW_TSENE_VOLT_ALARM_STATE],
+ FBNIC_FW_TSENE_ALARM_UNKNOWN);
+ if (alarm != FBNIC_FW_TSENE_ALARM_UNKNOWN)
+ WRITE_ONCE(fbd->hwmon_cache.volt_alarm, alarm);
+
msg_err:
cmpl_data->result = err_resp ? : err;
complete(&cmpl_data->done);
@@ -1651,6 +1708,82 @@ 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_U32(FBNIC_FW_TSENE_THERM_ALARM),
+ FBNIC_TLV_ATTR_U32(FBNIC_FW_TSENE_VOLT_ALARM),
+ 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)
+{
+ struct fbnic_dev *fbd = opaque;
+ bool rec_flag = false;
+ u32 alarm;
+ s32 value;
+
+ if (results[FBNIC_FW_TSENE_THERM_ALARM]) {
+ bool have_temp = !!results[FBNIC_FW_TSENE_THERMAL];
+
+ alarm = fta_get_uint(results, FBNIC_FW_TSENE_THERM_ALARM);
+ value = fta_get_sint(results, FBNIC_FW_TSENE_THERMAL);
+ if (!have_temp)
+ dev_err(fbd->dev, "Thermal alarm %u received with no temperature!\n",
+ alarm);
+ else if (alarm != FBNIC_FW_TSENE_ALARM_NORMAL)
+ dev_err(fbd->dev, "Thermal alarm %u, temperature is currently %dmC!\n",
+ alarm, value);
+
+ if (alarm == FBNIC_FW_TSENE_ALARM_DEPRECATED) {
+ /* Nothing to derive the range from, so do not guess */
+ if (have_temp)
+ fbnic_hwmon_old_notify_event(fbd,
+ FBNIC_SENSOR_TEMP,
+ value);
+ } else {
+ WRITE_ONCE(fbd->hwmon_cache.temp_alarm, alarm);
+ fbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_TEMP);
+ }
+ rec_flag = true;
+ }
+
+ if (results[FBNIC_FW_TSENE_VOLT_ALARM]) {
+ bool have_volt = !!results[FBNIC_FW_TSENE_VOLTAGE];
+
+ alarm = fta_get_uint(results, FBNIC_FW_TSENE_VOLT_ALARM);
+ value = fta_get_sint(results, FBNIC_FW_TSENE_VOLTAGE);
+ if (!have_volt)
+ dev_err(fbd->dev, "Voltage alarm %u received with no voltage!\n",
+ alarm);
+ else if (alarm != FBNIC_FW_TSENE_ALARM_NORMAL)
+ dev_err(fbd->dev, "Voltage alarm %u, voltage is currently %dmV!\n",
+ alarm, value);
+
+ if (alarm == FBNIC_FW_TSENE_ALARM_DEPRECATED) {
+ /* Nothing to derive the range from, so do not guess */
+ if (have_volt)
+ fbnic_hwmon_old_notify_event(fbd,
+ FBNIC_SENSOR_VOLTAGE,
+ value);
+ } else {
+ WRITE_ONCE(fbd->hwmon_cache.volt_alarm, alarm);
+ fbnic_hwmon_notify_event(fbd, FBNIC_SENSOR_VOLTAGE);
+ }
+ rec_flag = true;
+ }
+
+ if (!rec_flag) {
+ dev_warn(fbd->dev,
+ "Threshold exceeded message received but no alarm found!\n");
+ return -EINVAL;
+ }
+
+ 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,
@@ -1679,6 +1812,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 f47669129c9de..3b47872774088 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;
@@ -59,6 +60,18 @@ enum {
(BIT(FBNIC_FW_CAP_F_BMC_TCAM_REINIT) | \
BIT(FBNIC_FW_CAP_F_BMC_MACDA_SYNC))
+/* 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 {
unsigned long state;
struct {
@@ -72,6 +85,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 {
@@ -224,6 +239,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,
@@ -254,6 +270,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
};
@@ -284,9 +306,31 @@ enum {
FBNIC_FW_TSENE_THERM = 0x0,
FBNIC_FW_TSENE_VOLT = 0x1,
FBNIC_FW_TSENE_ERROR = 0x2,
+ FBNIC_FW_TSENE_THERM_ALARM_STATE = 0x3,
+ FBNIC_FW_TSENE_VOLT_ALARM_STATE = 0x4,
FBNIC_FW_TSENE_MSG_MAX
};
+enum {
+ FBNIC_FW_TSENE_THERM_ALARM = 0x0,
+ FBNIC_FW_TSENE_VOLT_ALARM = 0x1,
+ FBNIC_FW_TSENE_THERMAL = 0x2,
+ FBNIC_FW_TSENE_VOLTAGE = 0x3,
+ FBNIC_FW_TSENE_EXCEEDED_MSG_MAX,
+};
+
+enum {
+ FBNIC_FW_TSENE_ALARM_NORMAL = 0x0,
+ FBNIC_FW_TSENE_ALARM_DEPRECATED = 0x1,
+ FBNIC_FW_TSENE_ALARM_BELOW_MIN = 0x2,
+ FBNIC_FW_TSENE_ALARM_ABOVE_MAX = 0x3,
+ FBNIC_FW_TSENE_ALARM_CRIT = 0x4,
+ /* Driver internal, never sent by firmware. 0xff so its out of
+ * range wherever the range is held in a u8.
+ */
+ FBNIC_FW_TSENE_ALARM_UNKNOWN = 0xff,
+};
+
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 def8598aceecf..9fa9eb843c689 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
@@ -2,41 +2,246 @@
/* 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_thr_visible(s32 thr)
{
- if (type == hwmon_temp)
- return FBNIC_SENSOR_TEMP;
- if (type == hwmon_in)
- return FBNIC_SENSOR_VOLTAGE;
-
- return -EOPNOTSUPP;
+ return thr == FBNIC_SENSOR_NO_DATA ? 0 : 0444;
}
static umode_t fbnic_hwmon_is_visible(const void *drvdata,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
- if (type == hwmon_temp && attr == hwmon_temp_input)
- return 0444;
- if (type == hwmon_in && attr == hwmon_in_input)
- return 0444;
+ const struct fbnic_dev *fbd = drvdata;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ case hwmon_temp_min:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.temp.min);
+ case hwmon_temp_max:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.temp.max);
+ case hwmon_temp_crit:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.temp.crit);
+ case hwmon_temp_alarm:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.temp.min) &
+ fbnic_hwmon_thr_visible(fbd->fw_cap.temp.max) &
+ fbnic_hwmon_thr_visible(fbd->fw_cap.temp.crit);
+ }
+ break;
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ return 0444;
+ case hwmon_in_min:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.volt.min);
+ case hwmon_in_max:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.volt.max);
+ case hwmon_in_alarm:
+ return fbnic_hwmon_thr_visible(fbd->fw_cap.volt.min) &
+ fbnic_hwmon_thr_visible(fbd->fw_cap.volt.max);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+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 && cache->last_read == jiffies) {
+ *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 int fbnic_hwmon_read_threshold(long thr, long *val)
+{
+ if (thr == FBNIC_SENSOR_NO_DATA)
+ return -ENODATA;
+
+ *val = thr;
+ return 0;
+}
+
+static bool fbnic_hwmon_at_or_above(long val, s32 thr)
+{
+ return thr != FBNIC_SENSOR_NO_DATA && val >= thr;
+}
+
+static bool fbnic_hwmon_below(long val, s32 thr)
+{
+ return thr != FBNIC_SENSOR_NO_DATA && val < thr;
+}
+
+static u8 fbnic_hwmon_classify(const struct fbnic_threshold *thr, long val)
+{
+ if (fbnic_hwmon_at_or_above(val, thr->crit))
+ return FBNIC_FW_TSENE_ALARM_CRIT;
+ if (fbnic_hwmon_at_or_above(val, thr->max))
+ return FBNIC_FW_TSENE_ALARM_ABOVE_MAX;
+ if (fbnic_hwmon_below(val, thr->min))
+ return FBNIC_FW_TSENE_ALARM_BELOW_MIN;
+
+ return FBNIC_FW_TSENE_ALARM_NORMAL;
+}
+
+static int fbnic_hwmon_alarm_read(struct fbnic_dev *fbd,
+ enum hwmon_sensor_types type, long *val)
+{
+ struct fbnic_hwmon_cache *cache = &fbd->hwmon_cache;
+ const struct fbnic_threshold *thr;
+ u8 *cached, alarm;
+ long reading;
+ int id, err;
+
+ switch (type) {
+ case hwmon_temp:
+ thr = &fbd->fw_cap.temp;
+ cached = &cache->temp_alarm;
+ id = FBNIC_SENSOR_TEMP;
+ break;
+ case hwmon_in:
+ thr = &fbd->fw_cap.volt;
+ cached = &cache->volt_alarm;
+ id = FBNIC_SENSOR_VOLTAGE;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* Paired with WRITE_ONCE() on the mailbox thread. Firmware only
+ * reports on a threshold crossing, so nothing is cached until the
+ * first one. Read the sensor, whose response carries the range.
+ */
+ alarm = READ_ONCE(*cached);
+ if (alarm == FBNIC_FW_TSENE_ALARM_UNKNOWN) {
+ err = fbnic_hwmon_sensor_read(fbd, id, &reading);
+ if (err)
+ return err;
+
+ alarm = READ_ONCE(*cached);
+
+ /* Firmware too old to report a range, derive it instead */
+ if (alarm == FBNIC_FW_TSENE_ALARM_UNKNOWN)
+ alarm = fbnic_hwmon_classify(thr, reading);
+ }
+
+ *val = alarm != FBNIC_FW_TSENE_ALARM_NORMAL;
return 0;
}
+static int fbnic_hwmon_temp_read(struct fbnic_dev *fbd, u32 attr, long *val)
+{
+ switch (attr) {
+ case hwmon_temp_input:
+ return fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_TEMP, val);
+ 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_alarm:
+ return fbnic_hwmon_alarm_read(fbd, hwmon_temp, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int fbnic_hwmon_in_read(struct fbnic_dev *fbd, u32 attr, long *val)
+{
+ switch (attr) {
+ case hwmon_in_input:
+ return fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_VOLTAGE, val);
+ 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_alarm:
+ return fbnic_hwmon_alarm_read(fbd, hwmon_in, val);
+ default:
+ 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 +250,12 @@ 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_ALARM |
+ HWMON_T_MIN | HWMON_T_MAX | HWMON_T_CRIT),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT | HWMON_I_ALARM |
+ HWMON_I_MIN | HWMON_I_MAX),
NULL
};
@@ -57,25 +266,98 @@ 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)) {
+ 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_old_notify_event(struct fbnic_dev *fbd, int id, s32 value)
+{
+ const struct fbnic_threshold *thr;
+ u8 *cached;
+
+ switch (id) {
+ case FBNIC_SENSOR_TEMP:
+ thr = &fbd->fw_cap.temp;
+ cached = &fbd->hwmon_cache.temp_alarm;
+ break;
+ case FBNIC_SENSOR_VOLTAGE:
+ thr = &fbd->fw_cap.volt;
+ cached = &fbd->hwmon_cache.volt_alarm;
+ break;
+ default:
+ return;
+ }
+
+ /* Event arrived before the capability response containing
+ * the thresholds.
+ */
+ if (thr->min == FBNIC_SENSOR_NO_DATA ||
+ thr->max == FBNIC_SENSOR_NO_DATA)
+ return;
+
+ WRITE_ONCE(*cached, fbnic_hwmon_classify(thr, value));
+ fbnic_hwmon_notify_event(fbd, id);
+}
+
+void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id)
+{
+ enum hwmon_sensor_types type;
+ struct device *hwmon;
+ u32 attr;
+
+ if (!IS_REACHABLE(CONFIG_HWMON))
+ return;
+
+ switch (id) {
+ case FBNIC_SENSOR_TEMP:
+ type = hwmon_temp;
+ attr = hwmon_temp_alarm;
+ break;
+ case FBNIC_SENSOR_VOLTAGE:
+ type = hwmon_in;
+ attr = hwmon_in_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 (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 16271c717a5aa..3e1256ffd1411 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
@@ -892,60 +892,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,
@@ -959,7 +905,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 10f30e0e8f691..bde2daa656457 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/10/15 03:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 13716 output: 32 thoughts: 190 Thoughts: **Analyzing the Patch's Scope** Okay, so this patch is clearly focused on the `fbnic` directory within the network drivers. I see it's touching quite a few files: `fbnic.h`, `fbnic_fw.c`, `fbnic_fw.h`, `fbnic_hwmon.c`, `fbnic_mac.c`, and `fbnic_mac.h`. My immediate thought is, "What's `fbnic`? Is this a driver for Meta's custom NIC, possibly a hardware offload engine?" Given the location, that's the most logical assumption, but I need confirmation. Time to dig into the kernel source and search for more context on `fbnic`. I'll start with a quick search within the tree itself. I'm looking for either a definition or use case to confirm my initial hypothesis. |
| 4/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "fbnic",
"PathPrefixes": [
"drivers/net/ethernet/meta/"
]
}Results: {
"Output": "\nFull output is too long, showing 200 out of 8861 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (32 files in total):\ndrivers/net/ethernet/meta/Kconfig:1\ndrivers/net/ethernet/meta/Makefile:1\ndrivers/net/ethernet/meta/fbnic/Makefile:19\ndrivers/net/ethernet/meta/fbnic/fbnic.h:88\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.c:24\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.h:4\ndrivers/net/ethernet/meta/fbnic/fbnic_debugfs.c:123\ndrivers/net/ethernet/meta/fbnic/fbnic_devlink.c:90\ndrivers/net/ethernet/meta/fbnic/fbnic_drvinfo.h:1\ndrivers/net/ethernet/meta/fbnic/fbnic_ethtool.c:376\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:365\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.h:51\ndrivers/net/ethernet/meta/fbnic/fbnic_fw_log.c:18\ndrivers/net/ethernet/meta/fbnic/fbnic_fw_log.h:9\ndrivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c:207\ndrivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h:98\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:67\ndrivers/net/ethernet/meta/fbnic/fbnic_irq.c:86\ndrivers/net/ethernet/meta/fbnic/fbnic_mac.c:135\ndrivers/net/ethernet/meta/fbnic/fbnic_mac.h:32\ndrivers/net/ethernet/meta/fbnic/fbnic_mdio.c:34\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.c:149\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.h:37\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:169\ndrivers/net/ethernet/meta/fbnic/fbnic_phylink.c:51\ndrivers/net/ethernet/meta/fbnic/fbnic_rpc.c:154\ndrivers/net/ethernet/meta/fbnic/fbnic_rpc.h:34\ndrivers/net/ethernet/meta/fbnic/fbnic_time.c:69\ndrivers/net/ethernet/meta/fbnic/fbnic_tlv.c:110\ndrivers/net/ethernet/meta/fbnic/fbnic_tlv.h:45\ndrivers/net/ethernet/meta/fbnic/fbnic_txrx.c:537\ndrivers/net/ethernet/meta/fbnic/fbnic_txrx.h:48\n\ndrivers/net/ethernet/meta/Kconfig=20=config FBNIC\n--\ndrivers/net/ethernet/meta/Kconfig-35-\t To compile this driver as a module, choose M here. The module\ndrivers/net/ethernet/meta/Kconfig:36:\t will be called fbnic. MSI-X interrupt support is required.\ndrivers/net/ethernet/meta/Kconfig-37-\n--\ndrivers/net/ethernet/meta/Makefile-5-\ndrivers/net/ethernet/meta/Makefile:6:obj-$(CONFIG_FBNIC) += fbnic/\ndrivers/net/ethernet/meta/Makefile-7-obj-$(CONFIG_MPNIC) += mpnic/\n--\ndrivers/net/ethernet/meta/fbnic/Makefile-7-\ndrivers/net/ethernet/meta/fbnic/Makefile:8:obj-$(CONFIG_FBNIC) += fbnic.o\ndrivers/net/ethernet/meta/fbnic/Makefile-9-\ndrivers/net/ethernet/meta/fbnic/Makefile:10:fbnic-y := fbnic_csr.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:11:\t fbnic_debugfs.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:12:\t fbnic_devlink.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:13:\t fbnic_ethtool.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:14:\t fbnic_fw.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:15:\t fbnic_fw_log.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:16:\t fbnic_hw_stats.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:17:\t fbnic_hwmon.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:18:\t fbnic_irq.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:19:\t fbnic_mac.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:20:\t fbnic_netdev.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:21:\t fbnic_pci.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:22:\t fbnic_phylink.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:23:\t fbnic_rpc.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:24:\t fbnic_mdio.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:25:\t fbnic_time.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:26:\t fbnic_tlv.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:27:\t fbnic_txrx.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile-28-# End of objects\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-12-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:13:#include \"fbnic_csr.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:14:#include \"fbnic_fw.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:15:#include \"fbnic_fw_log.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:16:#include \"fbnic_hw_stats.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:17:#include \"fbnic_mac.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:18:#include \"fbnic_rpc.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h-19-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:20:struct fbnic_napi_vector;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-21-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-24-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:25:struct fbnic_hwmon_cache {\ndrivers/net/ethernet/meta/fbnic/fbnic.h-26-\tunsigned long last_read;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-32-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:33:struct fbnic_dev {\ndrivers/net/ethernet/meta/fbnic/fbnic.h-34-\tstruct device *dev;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-37-\tstruct device *hwmon;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:38:\tstruct fbnic_hwmon_cache hwmon_cache;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-39-\tstruct devlink_health_reporter *fw_reporter;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-43-\tu32 __iomem *uc_addr4;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:44:\tconst struct fbnic_mac *mac;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-45-\tunsigned int fw_msix_vector;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-55-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:56:\tstruct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:57:\tstruct fbnic_fw_cap fw_cap;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:58:\tstruct fbnic_fw_completion *cmpl_data[FBNIC_MBX_CMPL_SLOTS];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-59-\t/* Lock protecting Tx Mailbox queue to prevent possible races */\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-72-\t/* Local copy of the devices TCAM */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:73:\tstruct fbnic_act_tcam act_tcam[FBNIC_RPC_TCAM_ACT_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:74:\tstruct fbnic_mac_addr mac_addr[FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-75-\tu8 mac_addr_boundary;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-78-\t/* IP TCAM */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:79:\tstruct fbnic_ip_addr ip_src[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:80:\tstruct fbnic_ip_addr ip_dst[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:81:\tstruct fbnic_ip_addr ipo_src[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:82:\tstruct fbnic_ip_addr ipo_dst[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-83-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-86-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:87:\t/* Lock protecting writes to @time_high, @time_offset of fbnic_netdev,\ndrivers/net/ethernet/meta/fbnic/fbnic.h-88-\t * and the HW time CSR machinery.\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-101-\t/* Local copy of hardware statistics */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:102:\tstruct fbnic_hw_stats hw_stats;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-103-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-107-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:108:\tstruct fbnic_fw_log fw_log;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-109-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h=122=enum {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-127-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:128:static inline bool fbnic_present(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-129-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-132-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:133:static inline void fbnic_wr32(struct fbnic_dev *fbd, u32 reg, u32 val)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-134-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-140-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:141:u32 fbnic_rd32(struct fbnic_dev *fbd, u32 reg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-142-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:143:static inline void fbnic_wrfl(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-144-{\ndrivers/net/ethernet/meta/fbnic/fbnic.h:145:\tfbnic_rd32(fbd, FBNIC_MASTER_SPARE_0);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-146-}\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h=148=static inline void\ndrivers/net/ethernet/meta/fbnic/fbnic.h:149:fbnic_rmw32(struct fbnic_dev *fbd, u32 reg, u32 mask, u32 val)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-150-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-152-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:153:\tv = fbnic_rd32(fbd, reg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-154-\tv \u0026= ~mask;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-155-\tv |= val;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:156:\tfbnic_wr32(fbd, reg, v);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-157-}\ndrivers/net/ethernet/meta/fbnic/fbnic.h-158-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:159:#define wr32(_f, _r, _v)\tfbnic_wr32(_f, _r, _v)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:160:#define rd32(_f, _r)\t\tfbnic_rd32(_f, _r)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:161:#define wrfl(_f)\t\tfbnic_wrfl(_f)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-162-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:163:bool fbnic_fw_present(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:164:u32 fbnic_fw_rd32(struct fbnic_dev *fbd, u32 reg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:165:void fbnic_fw_wr32(struct fbnic_dev *fbd, u32 reg, u32 val);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-166-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:167:#define fw_rd32(_f, _r)\t\tfbnic_fw_rd32(_f, _r)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:168:#define fw_wr32(_f, _r, _v)\tfbnic_fw_wr32(_f, _r, _v)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:169:#define fw_wrfl(_f)\t\tfbnic_fw_rd32(_f, FBNIC_FW_ZERO_REG)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-170-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:171:static inline bool fbnic_bmc_present(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-172-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-175-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:176:static inline bool fbnic_bmc_all_multi(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-177-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-180-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:181:static inline bool fbnic_init_failure(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-182-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-185-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:186:extern char fbnic_driver_name[];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-187-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:188:void fbnic_devlink_free(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:189:struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:190:int fbnic_devlink_health_create(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:191:void fbnic_devlink_health_destroy(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:192:void fbnic_devlink_register(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:193:void fbnic_devlink_unregister(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-194-void __printf(2, 3)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:195:fbnic_devlink_fw_report(struct fbnic_dev *fbd, const char *format, ...);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:196:void fbnic_devlink_otp_check(struct fbnic_dev *fbd, const char *msg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-197-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:198:int fbnic_fw_request_mbx(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:199:void fbnic_fw_free_mbx(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-200-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:201:void fbnic_hwmon_register(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:202:void fbnic_hwmon_unregister(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:203:void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:204:void fbnic_hwmon_old_notify_event(struct fbnic_dev *fbd, int id, s32 value);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-205-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:206:int fbnic_mac_request_irq(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:207:void fbnic_mac_free_irq(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-208-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:209:void fbnic_napi_name_irqs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:210:int fbnic_napi_request_irq(struct fbnic_dev *fbd,\ndrivers/net/ethernet/meta/fbnic/fbnic.h:211:\t\t\t struct fbnic_napi_vector *nv);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:212:void fbnic_napi_free_irq(struct fbnic_dev *fbd,\ndrivers/net/ethernet/meta/fbnic/fbnic.h:213:\t\t\t struct fbnic_napi_vector *nv);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:214:void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:215:int fbnic_request_irq(struct fbnic_dev *dev, int nr, irq_handler_t handler,\ndrivers/net/ethernet/meta/fbnic/fbnic.h-216-\t\t unsigned long flags, const char *name, void *data);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:217:void fbnic_free_irq(struct fbnic_dev *dev, int nr, void *data);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-218-\ndrivers/net/ethernet/meta/fbnic/fbnic.h-219-/**\ndrivers/net/ethernet/meta/fbnic/fbnic.h:220: * enum fbnic_msix_self_test_codes - return codes from self test routines\ndrivers/net/ethernet/meta/fbnic/fbnic.h-221- *\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-235- */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:236:enum fbnic_msix_self_test_codes {\ndrivers/net/ethernet/meta/fbnic/fbnic.h-237-\tFBNIC_TEST_MSIX_SUCCESS = 0,\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-247-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:248:enum fbnic_msix_self_test_codes fbnic_msix_test(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-249-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:250:void fbnic_free_irqs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:251:int fbnic_alloc_irqs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-252-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:253:void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,\ndrivers/net/ethernet/meta/fbnic/fbnic.h-254-\t\t\t\t const size_t str_sz);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-255-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:256:void fbnic_dbg_fbd_init(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:257:void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:258:void fbnic_dbg_init(void);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:259:void fbnic_dbg_exit(void);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-260-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:261:void fbnic_rpc_reset_valid_entries(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-262-\n\n"
} |
| 5/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 20627 output: 37 thoughts: 25 Thoughts: Here's my take on those thoughts, tailored for an expert audience: **Investigating the FBNIC Configuration** Alright, let's dive right in. The mention of FBNIC immediately flags my curiosity. My first instinct, as always, is to go straight to the source – the Kconfig file. Specifically, I'm heading to `drivers/net/ethernet/meta/Kconfig`. This is where I'd expect to find the definitive documentation, the conditional logic, and the associated dependencies related to FBNIC within this specific driver context. I'm expecting to find at least: * **A `config FBNIC` symbol:** This is the obvious starting point. It'll define the core feature toggle. * **Documentation:** Clear and concise details about what FBNIC actually *is* within this kernel version, its purpose (e.g., hardware offload, specific NIC vendor support, etc.), and any relevant caveats or limitations. I'm hoping it's well-written, since the quality of documentation in Kconfig can be a good indicator of overall code maintainability. * **Dependencies:** I'm particularly interested in seeing what other features or drivers this FBNIC configuration is tied to. Are there specific hardware requirements? Are there conflicts with other network features? This will help me understand its integration within the larger networking stack. * **Default settings/options:** Any default values or configurable parameters for FBNIC? If so, are they documented, and are they well-reasoned? Essentially, my goal is to quickly grasp the essence of FBNIC within the broader network driver ecosystem, and how it can be controlled, and enabled. |
| 6/2 | 2026/10/15 03:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/meta/Kconfig",
"FirstLine": 1,
"LineCount": 50
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\t#\n 3:\t# Meta Platforms network device configuration\n 4:\t#\n 5:\t\n 6:\tconfig NET_VENDOR_META\n 7:\t\tbool \"Meta Platforms devices\"\n 8:\t\tdefault y\n 9:\t\thelp\n 10:\t\t If you have a network (Ethernet) card designed by Meta, say Y.\n 11:\t\t That's Meta as in the parent company of Facebook.\n 12:\t\n 13:\t\t Note that the answer to this question doesn't directly affect the\n 14:\t\t kernel: saying N will just cause the configurator to skip all\n 15:\t\t the questions about Meta cards. If you say Y, you will be asked for\n 16:\t\t your specific card in the following questions.\n 17:\t\n 18:\tif NET_VENDOR_META\n 19:\t\n 20:\tconfig FBNIC\n 21:\t\ttristate \"Meta Platforms Host Network Interface\"\n 22:\t\tdepends on 64BIT || COMPILE_TEST\n 23:\t\tdepends on !S390\n 24:\t\tdepends on MAX_SKB_FRAGS \u003c 22\n 25:\t\tdepends on PCI_MSI\n 26:\t\tdepends on PTP_1588_CLOCK_OPTIONAL\n 27:\t\tselect NET_DEVLINK\n 28:\t\tselect PAGE_POOL\n 29:\t\tselect PCS_XPCS\n 30:\t\tselect PHYLINK\n 31:\t\tselect PLDMFW\n 32:\t\thelp\n 33:\t\t This driver supports Meta Platforms Host Network Interface.\n 34:\t\n 35:\t\t To compile this driver as a module, choose M here. The module\n 36:\t\t will be called fbnic. MSI-X interrupt support is required.\n 37:\t\n 38:\tconfig MPNIC\n 39:\t\ttristate \"Meta Platforms Network Interface Controller\"\n 40:\t\tdepends on 64BIT || COMPILE_TEST\n 41:\t\tdepends on !S390\n 42:\t\tdepends on PCI_MSI\n 43:\t\tselect PAGE_POOL\n 44:\t\thelp\n 45:\t\t This driver supports the Meta Platforms Network Interface\n 46:\t\t Controller.\n 47:\t\n 48:\t\t To compile this driver as a module, choose M here. The module\n 49:\t\t will be called mpnic.\n 50:\t\n"
} |
| 7/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21686 output: 47 thoughts: 23 Thoughts: Okay, let's dive in. **Inspecting the FB-NIC Probe Process** Right, time to get my hands dirty. I need to understand exactly how this fbnic device is being probed. The first logical step is to crack open `fbnic_pci.c`. That's where I expect to find the meat of the initialization and detection logic for this particular network card. Hopefully, it's well-commented... because I'm betting that understanding this probe routine will unlock a whole host of further questions about how the driver interacts with the hardware. |
| 8/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "pci_register_driver|fbnic_pci_driver",
"PathPrefixes": [
"drivers/net/ethernet/meta/fbnic/"
]
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_pci.c=652=static int __init fbnic_init_module(void)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-657-\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:658:\terr = pci_register_driver(\u0026fbnic_driver);\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-659-\tif (err) {\n"
} |
| 9/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 22024 output: 47 thoughts: 20 Thoughts: Here's my thought process, as requested: **Navigating the `fbnic_pci.c` Driver Code** Okay, so I need to zero in on the `fbnic_driver` in `fbnic_pci.c`. My immediate goal is to understand how this driver is structured and how it interacts with the PCI bus. I'm going to start by looking around that function – I'll be looking for things like initialization, probe, remove, and any related structures or function calls that are tied to it. This is where the core of the PCI device interaction should be defined. I'm particularly interested in how the hardware resources are mapped, and how the driver handles interrupts. This means I'll be watching for calls to PCI configuration registers, memory mapping functions (like `pci_iomap()`, if it's there), and interrupt handling routines. I'm expecting to see calls to common PCI helper functions, and probably some device-specific setup as well. Let's see what's actually in there. |
| 10/2 | 2026/10/15 03:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/meta/fbnic/fbnic_pci.c",
"FirstLine": 600,
"LineCount": 70
}Results: {
"Contents": " 600:\t\t/* Request a slot reset */\n 601:\t\treturn PCI_ERS_RESULT_NEED_RESET;\n 602:\t}\n 603:\t\n 604:\tstatic pci_ers_result_t fbnic_err_slot_reset(struct pci_dev *pdev)\n 605:\t{\n 606:\t\tint err;\n 607:\t\n 608:\t\tpci_set_power_state(pdev, PCI_D0);\n 609:\t\tpci_restore_state(pdev);\n 610:\t\n 611:\t\tif (pci_enable_device_mem(pdev)) {\n 612:\t\t\tdev_err(\u0026pdev-\u003edev,\n 613:\t\t\t\t\"Cannot re-enable PCI device after reset.\\n\");\n 614:\t\t\treturn PCI_ERS_RESULT_DISCONNECT;\n 615:\t\t}\n 616:\t\n 617:\t\t/* Restore device to previous state */\n 618:\t\terr = __fbnic_pm_resume(\u0026pdev-\u003edev);\n 619:\t\n 620:\t\treturn err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;\n 621:\t}\n 622:\t\n 623:\tstatic void fbnic_err_resume(struct pci_dev *pdev)\n 624:\t{\n 625:\t\t__fbnic_pm_attach(\u0026pdev-\u003edev);\n 626:\t}\n 627:\t\n 628:\tstatic const struct pci_error_handlers fbnic_err_handler = {\n 629:\t\t.error_detected\t= fbnic_err_error_detected,\n 630:\t\t.slot_reset\t= fbnic_err_slot_reset,\n 631:\t\t.resume\t\t= fbnic_err_resume,\n 632:\t};\n 633:\t\n 634:\tstatic struct pci_driver fbnic_driver = {\n 635:\t\t.name\t\t= fbnic_driver_name,\n 636:\t\t.id_table\t= fbnic_pci_tbl,\n 637:\t\t.probe\t\t= fbnic_probe,\n 638:\t\t.remove\t\t= fbnic_remove,\n 639:\t\t.driver.pm\t= \u0026fbnic_pm_ops,\n 640:\t\t.shutdown\t= fbnic_shutdown,\n 641:\t\t.err_handler\t= \u0026fbnic_err_handler,\n 642:\t};\n 643:\t\n 644:\t/**\n 645:\t * fbnic_init_module - Driver Registration Routine\n 646:\t *\n 647:\t * The first routine called when the driver is loaded. All it does is\n 648:\t * register with the PCI subsystem.\n 649:\t *\n 650:\t * Return: 0 on success, negative on failure\n 651:\t **/\n 652:\tstatic int __init fbnic_init_module(void)\n 653:\t{\n 654:\t\tint err;\n 655:\t\n 656:\t\tfbnic_dbg_init();\n 657:\t\n 658:\t\terr = pci_register_driver(\u0026fbnic_driver);\n 659:\t\tif (err) {\n 660:\t\t\tfbnic_dbg_exit();\n 661:\t\t\tgoto out;\n 662:\t\t}\n 663:\t\n 664:\t\tpr_info(DRV_SUMMARY \" (%s)\", fbnic_driver.name);\n 665:\tout:\n 666:\t\treturn err;\n 667:\t}\n 668:\tmodule_init(fbnic_init_module);\n 669:\t\n"
} |
| 11/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23307 output: 40 thoughts: 22 Thoughts: Okay, let's dive in. Here's my thought process regarding the next step in this investigation: **Examining the `fbnic_pci_tbl` for PCI Device IDs** Alright, before I get too deep into anything else, my gut tells me to check the `fbnic_pci_tbl`. That table holds the key, doesn't it? It's where I can quickly identify which PCI device IDs are actually associated with that `fbnic` device. Understanding that mapping is crucial. Knowing those specific IDs will help me narrow down what I'm dealing with. I need to be sure this is connected to a network adapter and not, say, a graphics card. So, time to pull up the source and see what the device IDs are that `fbnic` is known to support. Let's see what we can find. |
| 12/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "fbnic_pci_tbl",
"PathPrefixes": [
"drivers/net/ethernet/meta/fbnic/"
]
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_pci.c=26=static const struct fbnic_info *fbnic_info_tbl[] = {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-29-\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:30:static const struct pci_device_id fbnic_pci_tbl[] = {\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-31-\t{ PCI_DEVICE_DATA(META, FBNIC_ASIC, fbnic_board_asic) },\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-34-};\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:35:MODULE_DEVICE_TABLE(pci, fbnic_pci_tbl);\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-36-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c=214=static void fbnic_service_task(struct work_struct *work)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-250- * @pdev: PCI device information struct\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:251: * @ent: entry in fbnic_pci_tbl\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-252- *\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c=634=static struct pci_driver fbnic_driver = {\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-635-\t.name\t\t= fbnic_driver_name,\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:636:\t.id_table\t= fbnic_pci_tbl,\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-637-\t.probe\t\t= fbnic_probe,\n"
} |
| 13/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 24107 output: 51 thoughts: 92 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience:
**Analyzing Potential FBNIC PCI Device Initialization**
Alright, let's dive in. I'm looking at this `fbnic_pci_tbl` structure, specifically this line: `{ PCI_DEVICE_DATA(META, FBNIC_ASIC, fbnic_board_asic) },`. My initial thought is to determine what's going on with this entry. I need to understand what `META` represents within this context. Is this a real physical vendor ID? Does this indicate some kind of virtual or emulated hardware? The `fbnic_board_asic` suggests a specific ASIC, but the `META` prefix could complicate things.
My next step is to perform a targeted search within the relevant code base, ideally within the PCI device enumeration and driver registration sections. I'll be looking for either the definition of `PCI_DEVICE_DATA(META` or, if that macro's expansion isn't immediately revealing, a direct reference to `PCI_VENDOR_ID_META`. This should give me the context I need to figure out how this `META` vendor ID is being handled and what implications this has for the FBNIC's PCI device initialization and driver binding.
|
| 14/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "PCI_VENDOR_ID_META|PCI_DEVICE_ID_META",
"PathPrefixes": [
"include/linux/pci_ids.h",
"drivers/"
]
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_csr.h=9=struct fbnic_dev;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.h-39-\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.h:40:#define PCI_DEVICE_ID_META_FBNIC_ASIC\t\t0x0013\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.h-41-\n--\ndrivers/net/ethernet/meta/mpnic/mpnic_pci.c-15-\ndrivers/net/ethernet/meta/mpnic/mpnic_pci.c:16:#define PCI_DEVICE_ID_META_MPNIC\t0x0014\ndrivers/net/ethernet/meta/mpnic/mpnic_pci.c-17-\n--\ndrivers/net/ethernet/meta/mpnic/mpnic_pci.c=191=static const struct pci_device_id mpnic_pci_tbl[] = {\ndrivers/net/ethernet/meta/mpnic/mpnic_pci.c:192:\t{ PCI_VDEVICE(META, PCI_DEVICE_ID_META_MPNIC) },\ndrivers/net/ethernet/meta/mpnic/mpnic_pci.c-193-\t/* required last entry */\n--\ndrivers/ptp/ptp_ocp.c-31-\ndrivers/ptp/ptp_ocp.c:32:#define PCI_DEVICE_ID_META_TIMECARD\t\t0x0400\ndrivers/ptp/ptp_ocp.c-33-\n--\ninclude/linux/pci_ids.h-2618-\ninclude/linux/pci_ids.h:2619:#define PCI_VENDOR_ID_META\t\t0x1d9b\ninclude/linux/pci_ids.h-2620-\n"
} |
| 15/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 25008 output: 37 thoughts: 296 Thoughts: **My Assessment of the `fbnic` Driver's Fuzzing Suitability** Okay, so `fbnic` is a driver specifically for Meta's ASIC network interface card – the `PCI_DEVICE_ID_META_FBNIC_ASIC` and `PCI_VENDOR_ID_META` identify it as such. The immediate question in my mind is whether this is emulated anywhere. Is `fbnic` something I can reliably run and test within standard QEMU or even Google Compute Engine? And the answer is no, it's pretty clear that QEMU doesn't emulate Meta's Host Network Interface. Alright, let's circle back to the negative criteria outlined in Section 2. We need to determine if this falls into a category where fuzzing is pointless. The relevant section, regarding "Structurally unreachable hardware," jumps out at me: "...Vendor-specific PCIe switches, SmartNICs... requiring physical ASIC/PCIe cards not emulated in standard QEMU." Bingo. It looks like it could apply, given it requires Meta's specific ASIC card. However, let me not make any assumptions yet. Let's verify this, I need to see if there's any other way `fbnic` can be reached. Can it be loaded or instantiated without that physical PCI device? Are there any mock interfaces, test interfaces, or virtual drivers I could hook into? I will start to hunt around for the `fbnic_probe` function or anything that references `fbnic` to see if there are any other paths. If I can prove there's no way to reach it without the physical hardware, then I know I can safely return `WorthFuzzing=false`. |
| 16/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "fbnic_probe",
"PathPrefixes": [
"drivers/net/ethernet/meta/fbnic/"
]
}Results: {
"Output": "drivers/net/ethernet/meta/fbnic/fbnic_pci.c=214=static void fbnic_service_task(struct work_struct *work)\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-248-/**\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:249: * fbnic_probe - Device Initialization Routine\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-250- * @pdev: PCI device information struct\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-258- **/\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:259:static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-260-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c=634=static struct pci_driver fbnic_driver = {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-636-\t.id_table\t= fbnic_pci_tbl,\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:637:\t.probe\t\t= fbnic_probe,\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c-638-\t.remove\t\t= fbnic_remove,\n"
} |
| 17/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 26106 output: 31 thoughts: 37 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, and delivered as a first-person internal monologue: **Investigating Potential FB-NIC Dependencies** Right, so I'm digging into this `fbnic` situation, and I need to get a really good grasp on its usage within the kernel. My immediate concern is, are there any *other* places, beyond the obvious, that might be calling `fbnic_probe` or, even more critically, instantiating an `fbnic_dev` structure? We all know how easy it is to miss a subtle dependency, especially in a large codebase. Therefore, let's cast a wide net. I'm going to launch a comprehensive search – not just within a specific module or subsystem, but a full, kernel-wide search for the string `fbnic`. I need to ensure I uncover every single instance, including those obscure calls that might be buried deep within a vendor-specific driver or a legacy component that someone might have forgotten about. This breadth is essential to prevent any future surprises. I'm going to look for any potential side-effects that could cause future problems. I need to be completely thorough. |
| 18/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "fbnic_",
"PathPrefixes": [
"drivers/net/ethernet/"
]
}Results: {
"Output": "\nFull output is too long, showing 200 out of 8813 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (29 files in total):\ndrivers/net/ethernet/meta/fbnic/Makefile:18\ndrivers/net/ethernet/meta/fbnic/fbnic.h:88\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.c:23\ndrivers/net/ethernet/meta/fbnic/fbnic_csr.h:4\ndrivers/net/ethernet/meta/fbnic/fbnic_debugfs.c:122\ndrivers/net/ethernet/meta/fbnic/fbnic_devlink.c:89\ndrivers/net/ethernet/meta/fbnic/fbnic_ethtool.c:375\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.c:363\ndrivers/net/ethernet/meta/fbnic/fbnic_fw.h:51\ndrivers/net/ethernet/meta/fbnic/fbnic_fw_log.c:17\ndrivers/net/ethernet/meta/fbnic/fbnic_fw_log.h:9\ndrivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c:206\ndrivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h:98\ndrivers/net/ethernet/meta/fbnic/fbnic_hwmon.c:65\ndrivers/net/ethernet/meta/fbnic/fbnic_irq.c:85\ndrivers/net/ethernet/meta/fbnic/fbnic_mac.c:134\ndrivers/net/ethernet/meta/fbnic/fbnic_mac.h:32\ndrivers/net/ethernet/meta/fbnic/fbnic_mdio.c:32\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.c:148\ndrivers/net/ethernet/meta/fbnic/fbnic_netdev.h:37\ndrivers/net/ethernet/meta/fbnic/fbnic_pci.c:168\ndrivers/net/ethernet/meta/fbnic/fbnic_phylink.c:50\ndrivers/net/ethernet/meta/fbnic/fbnic_rpc.c:151\ndrivers/net/ethernet/meta/fbnic/fbnic_rpc.h:34\ndrivers/net/ethernet/meta/fbnic/fbnic_time.c:68\ndrivers/net/ethernet/meta/fbnic/fbnic_tlv.c:110\ndrivers/net/ethernet/meta/fbnic/fbnic_tlv.h:45\ndrivers/net/ethernet/meta/fbnic/fbnic_txrx.c:535\ndrivers/net/ethernet/meta/fbnic/fbnic_txrx.h:48\n\ndrivers/net/ethernet/meta/fbnic/Makefile=8=obj-$(CONFIG_FBNIC) += fbnic.o\ndrivers/net/ethernet/meta/fbnic/Makefile-9-\ndrivers/net/ethernet/meta/fbnic/Makefile:10:fbnic-y := fbnic_csr.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:11:\t fbnic_debugfs.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:12:\t fbnic_devlink.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:13:\t fbnic_ethtool.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:14:\t fbnic_fw.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:15:\t fbnic_fw_log.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:16:\t fbnic_hw_stats.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:17:\t fbnic_hwmon.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:18:\t fbnic_irq.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:19:\t fbnic_mac.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:20:\t fbnic_netdev.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:21:\t fbnic_pci.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:22:\t fbnic_phylink.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:23:\t fbnic_rpc.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:24:\t fbnic_mdio.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:25:\t fbnic_time.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:26:\t fbnic_tlv.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile:27:\t fbnic_txrx.o \\\ndrivers/net/ethernet/meta/fbnic/Makefile-28-# End of objects\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-12-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:13:#include \"fbnic_csr.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:14:#include \"fbnic_fw.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:15:#include \"fbnic_fw_log.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:16:#include \"fbnic_hw_stats.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:17:#include \"fbnic_mac.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h:18:#include \"fbnic_rpc.h\"\ndrivers/net/ethernet/meta/fbnic/fbnic.h-19-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:20:struct fbnic_napi_vector;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-21-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-24-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:25:struct fbnic_hwmon_cache {\ndrivers/net/ethernet/meta/fbnic/fbnic.h-26-\tunsigned long last_read;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-32-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:33:struct fbnic_dev {\ndrivers/net/ethernet/meta/fbnic/fbnic.h-34-\tstruct device *dev;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-37-\tstruct device *hwmon;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:38:\tstruct fbnic_hwmon_cache hwmon_cache;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-39-\tstruct devlink_health_reporter *fw_reporter;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-43-\tu32 __iomem *uc_addr4;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:44:\tconst struct fbnic_mac *mac;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-45-\tunsigned int fw_msix_vector;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-55-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:56:\tstruct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:57:\tstruct fbnic_fw_cap fw_cap;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:58:\tstruct fbnic_fw_completion *cmpl_data[FBNIC_MBX_CMPL_SLOTS];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-59-\t/* Lock protecting Tx Mailbox queue to prevent possible races */\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-72-\t/* Local copy of the devices TCAM */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:73:\tstruct fbnic_act_tcam act_tcam[FBNIC_RPC_TCAM_ACT_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:74:\tstruct fbnic_mac_addr mac_addr[FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-75-\tu8 mac_addr_boundary;\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-78-\t/* IP TCAM */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:79:\tstruct fbnic_ip_addr ip_src[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:80:\tstruct fbnic_ip_addr ip_dst[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:81:\tstruct fbnic_ip_addr ipo_src[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h:82:\tstruct fbnic_ip_addr ipo_dst[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-83-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-86-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:87:\t/* Lock protecting writes to @time_high, @time_offset of fbnic_netdev,\ndrivers/net/ethernet/meta/fbnic/fbnic.h-88-\t * and the HW time CSR machinery.\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-101-\t/* Local copy of hardware statistics */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:102:\tstruct fbnic_hw_stats hw_stats;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-103-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-107-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:108:\tstruct fbnic_fw_log fw_log;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-109-\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h=122=enum {\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-127-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:128:static inline bool fbnic_present(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-129-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-132-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:133:static inline void fbnic_wr32(struct fbnic_dev *fbd, u32 reg, u32 val)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-134-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-140-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:141:u32 fbnic_rd32(struct fbnic_dev *fbd, u32 reg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-142-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:143:static inline void fbnic_wrfl(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-144-{\ndrivers/net/ethernet/meta/fbnic/fbnic.h:145:\tfbnic_rd32(fbd, FBNIC_MASTER_SPARE_0);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-146-}\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h=148=static inline void\ndrivers/net/ethernet/meta/fbnic/fbnic.h:149:fbnic_rmw32(struct fbnic_dev *fbd, u32 reg, u32 mask, u32 val)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-150-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-152-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:153:\tv = fbnic_rd32(fbd, reg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-154-\tv \u0026= ~mask;\ndrivers/net/ethernet/meta/fbnic/fbnic.h-155-\tv |= val;\ndrivers/net/ethernet/meta/fbnic/fbnic.h:156:\tfbnic_wr32(fbd, reg, v);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-157-}\ndrivers/net/ethernet/meta/fbnic/fbnic.h-158-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:159:#define wr32(_f, _r, _v)\tfbnic_wr32(_f, _r, _v)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:160:#define rd32(_f, _r)\t\tfbnic_rd32(_f, _r)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:161:#define wrfl(_f)\t\tfbnic_wrfl(_f)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-162-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:163:bool fbnic_fw_present(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:164:u32 fbnic_fw_rd32(struct fbnic_dev *fbd, u32 reg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:165:void fbnic_fw_wr32(struct fbnic_dev *fbd, u32 reg, u32 val);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-166-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:167:#define fw_rd32(_f, _r)\t\tfbnic_fw_rd32(_f, _r)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:168:#define fw_wr32(_f, _r, _v)\tfbnic_fw_wr32(_f, _r, _v)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:169:#define fw_wrfl(_f)\t\tfbnic_fw_rd32(_f, FBNIC_FW_ZERO_REG)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-170-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:171:static inline bool fbnic_bmc_present(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-172-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-175-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:176:static inline bool fbnic_bmc_all_multi(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-177-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-180-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:181:static inline bool fbnic_init_failure(struct fbnic_dev *fbd)\ndrivers/net/ethernet/meta/fbnic/fbnic.h-182-{\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-185-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:186:extern char fbnic_driver_name[];\ndrivers/net/ethernet/meta/fbnic/fbnic.h-187-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:188:void fbnic_devlink_free(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:189:struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:190:int fbnic_devlink_health_create(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:191:void fbnic_devlink_health_destroy(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:192:void fbnic_devlink_register(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:193:void fbnic_devlink_unregister(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-194-void __printf(2, 3)\ndrivers/net/ethernet/meta/fbnic/fbnic.h:195:fbnic_devlink_fw_report(struct fbnic_dev *fbd, const char *format, ...);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:196:void fbnic_devlink_otp_check(struct fbnic_dev *fbd, const char *msg);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-197-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:198:int fbnic_fw_request_mbx(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:199:void fbnic_fw_free_mbx(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-200-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:201:void fbnic_hwmon_register(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:202:void fbnic_hwmon_unregister(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:203:void fbnic_hwmon_notify_event(struct fbnic_dev *fbd, int id);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:204:void fbnic_hwmon_old_notify_event(struct fbnic_dev *fbd, int id, s32 value);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-205-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:206:int fbnic_mac_request_irq(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:207:void fbnic_mac_free_irq(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-208-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:209:void fbnic_napi_name_irqs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:210:int fbnic_napi_request_irq(struct fbnic_dev *fbd,\ndrivers/net/ethernet/meta/fbnic/fbnic.h:211:\t\t\t struct fbnic_napi_vector *nv);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:212:void fbnic_napi_free_irq(struct fbnic_dev *fbd,\ndrivers/net/ethernet/meta/fbnic/fbnic.h:213:\t\t\t struct fbnic_napi_vector *nv);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:214:void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:215:int fbnic_request_irq(struct fbnic_dev *dev, int nr, irq_handler_t handler,\ndrivers/net/ethernet/meta/fbnic/fbnic.h-216-\t\t unsigned long flags, const char *name, void *data);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:217:void fbnic_free_irq(struct fbnic_dev *dev, int nr, void *data);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-218-\ndrivers/net/ethernet/meta/fbnic/fbnic.h-219-/**\ndrivers/net/ethernet/meta/fbnic/fbnic.h:220: * enum fbnic_msix_self_test_codes - return codes from self test routines\ndrivers/net/ethernet/meta/fbnic/fbnic.h-221- *\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-235- */\ndrivers/net/ethernet/meta/fbnic/fbnic.h:236:enum fbnic_msix_self_test_codes {\ndrivers/net/ethernet/meta/fbnic/fbnic.h-237-\tFBNIC_TEST_MSIX_SUCCESS = 0,\n--\ndrivers/net/ethernet/meta/fbnic/fbnic.h-247-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:248:enum fbnic_msix_self_test_codes fbnic_msix_test(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-249-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:250:void fbnic_free_irqs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:251:int fbnic_alloc_irqs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-252-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:253:void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,\ndrivers/net/ethernet/meta/fbnic/fbnic.h-254-\t\t\t\t const size_t str_sz);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-255-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:256:void fbnic_dbg_fbd_init(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:257:void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:258:void fbnic_dbg_init(void);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:259:void fbnic_dbg_exit(void);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-260-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:261:void fbnic_rpc_reset_valid_entries(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-262-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:263:int fbnic_mdiobus_create(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-264-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:265:void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:266:int fbnic_csr_regs_len(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-267-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:268:void fbnic_config_txrx_usecs(struct fbnic_napi_vector *nv, u32 arm);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:269:void fbnic_config_rx_frames(struct fbnic_napi_vector *nv);\ndrivers/net/ethernet/meta/fbnic/fbnic.h:270:void fbnic_config_rx_cqe_nsecs(struct fbnic_dev *fbd);\ndrivers/net/ethernet/meta/fbnic/fbnic.h-271-\ndrivers/net/ethernet/meta/fbnic/fbnic.h:272:enum fbnic_boards {\ndrivers/net/ethernet/meta/fbnic/fbnic.h:273:\tfbnic_board_asic\n\n"
} |
| 19/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 33085 output: 47 thoughts: 32 Thoughts: Here's my thought process, as if I were considering this code: **Diving into the FBnic Probe** Okay, so I need to understand how this `fbnic` device is being initialized. My gut tells me that the probe function is the place to start, so let's head straight to `drivers/net/ethernet/meta/fbnic/fbnic_pci.c`. The naming convention strongly suggests this is the PCI version of the driver, which is probably what I'm dealing with. I need to quickly identify the key steps involved in device detection, resource allocation, and initialization. I'm looking for anything unusual or potentially problematic that might stick out. Let's see what `fbnic_probe` is really doing under the hood. |
| 20/2 | 2026/10/15 03:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/ethernet/meta/fbnic/fbnic_pci.c",
"FirstLine": 255,
"LineCount": 90
}Results: {
"Contents": " 255:\t * and a hardware reset occur.\n 256:\t *\n 257:\t * Return: 0 on success, negative on failure\n 258:\t **/\n 259:\tstatic int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n 260:\t{\n 261:\t\tconst struct fbnic_info *info = fbnic_info_tbl[ent-\u003edriver_data];\n 262:\t\tstruct net_device *netdev;\n 263:\t\tstruct fbnic_dev *fbd;\n 264:\t\tint err;\n 265:\t\n 266:\t\tif (pdev-\u003eerror_state != pci_channel_io_normal) {\n 267:\t\t\tdev_err(\u0026pdev-\u003edev,\n 268:\t\t\t\t\"PCI device still in an error state. Unable to load...\\n\");\n 269:\t\t\treturn -EIO;\n 270:\t\t}\n 271:\t\n 272:\t\terr = pcim_enable_device(pdev);\n 273:\t\tif (err) {\n 274:\t\t\tdev_err(\u0026pdev-\u003edev, \"PCI enable device failed: %d\\n\", err);\n 275:\t\t\treturn err;\n 276:\t\t}\n 277:\t\n 278:\t\terr = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(46));\n 279:\t\tif (err) {\n 280:\t\t\tdev_err(\u0026pdev-\u003edev, \"DMA configuration failed: %d\\n\", err);\n 281:\t\t\treturn err;\n 282:\t\t}\n 283:\t\n 284:\t\terr = pcim_iomap_regions(pdev, info-\u003ebar_mask, fbnic_driver_name);\n 285:\t\tif (err) {\n 286:\t\t\tdev_err(\u0026pdev-\u003edev,\n 287:\t\t\t\t\"pci_request_selected_regions failed: %d\\n\", err);\n 288:\t\t\treturn err;\n 289:\t\t}\n 290:\t\n 291:\t\tfbd = fbnic_devlink_alloc(pdev);\n 292:\t\tif (!fbd) {\n 293:\t\t\tdev_err(\u0026pdev-\u003edev, \"Devlink allocation failed\\n\");\n 294:\t\t\treturn -ENOMEM;\n 295:\t\t}\n 296:\t\n 297:\t\terr = fbnic_devlink_health_create(fbd);\n 298:\t\tif (err)\n 299:\t\t\tgoto free_fbd;\n 300:\t\n 301:\t\t/* Populate driver with hardware-specific info and handlers */\n 302:\t\tfbd-\u003emax_num_queues = info-\u003emax_num_queues;\n 303:\t\n 304:\t\tfbd-\u003eps_timeout = FBNIC_MAC_PS_TO_DEFAULT_MS;\n 305:\t\n 306:\t\tpci_set_master(pdev);\n 307:\t\tpci_save_state(pdev);\n 308:\t\n 309:\t\tINIT_DELAYED_WORK(\u0026fbd-\u003eservice_task, fbnic_service_task);\n 310:\t\n 311:\t\terr = fbnic_alloc_irqs(fbd);\n 312:\t\tif (err)\n 313:\t\t\tgoto err_destroy_health;\n 314:\t\n 315:\t\terr = fbnic_mac_init(fbd);\n 316:\t\tif (err) {\n 317:\t\t\tdev_err(\u0026pdev-\u003edev, \"Failed to initialize MAC: %d\\n\", err);\n 318:\t\t\tgoto free_irqs;\n 319:\t\t}\n 320:\t\n 321:\t\terr = fbnic_fw_log_init(fbd);\n 322:\t\tif (err)\n 323:\t\t\tdev_warn(fbd-\u003edev,\n 324:\t\t\t\t \"Unable to initialize firmware log buffer: %d\\n\",\n 325:\t\t\t\t err);\n 326:\t\n 327:\t\terr = fbnic_fw_request_mbx(fbd);\n 328:\t\tif (err) {\n 329:\t\t\tdev_err(\u0026pdev-\u003edev,\n 330:\t\t\t\t\"Firmware mailbox initialization failure\\n\");\n 331:\t\t\tgoto free_fw_log;\n 332:\t\t}\n 333:\t\n 334:\t\t/* Send the request to enable the FW logging to host. Note if this\n 335:\t\t * fails we ignore the error and just display a message as it is\n 336:\t\t * possible the FW is just too old to support the logging and needs\n 337:\t\t * to be updated.\n 338:\t\t */\n 339:\t\tfbnic_fw_log_enable(fbd, true);\n 340:\t\n 341:\t\tfbnic_devlink_register(fbd);\n 342:\t\tfbnic_devlink_otp_check(fbd, \"error detected during probe\");\n 343:\t\tfbnic_dbg_fbd_init(fbd);\n 344:\t\n"
} |
| 21/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 34697 output: 35 thoughts: 222 Thoughts: **My Assessment of the `fbnic` Situation** Okay, so `fbnic` is Meta's custom ASIC NIC, a Host Network Interface, specifically. That means it's a specialized piece of hardware. From what I'm reading, it's pretty clear that it *needs* a physical PCI device. This isn't something that can just be spun up in any old QEMU instance or GCE environment. It's tied to those physical ASICs with the specific vendor and device IDs – `PCI_VENDOR_ID_META` and `PCI_DEVICE_ID_META_FBNIC_ASIC` – and interacts with its firmware over the mailbox/MSI-X interface. So, emulating its behaviour in a generic environment isn't straightforward. The text is pointing out this issue, clearly. But hold on a second... Let's not jump to conclusions. I need to be thorough. Just because it *normally* requires the physical hardware doesn't necessarily mean there aren't *other* ways to interact with it, even if they're less common. Perhaps there are virtual functions using SR-IOV? Or maybe some software emulation exists – a "netdevsim" setup, perhaps? I'll need to dig deeper. I'm going to have to check the rest of the relevant tree and tools to see if the `fbnic` name shows up elsewhere. Let's see if there are any hints about a more abstract interaction method. |
| 22/2 | 2026/10/15 03:25 | tool | grepper |
0mError:no matches Args: {
"Expression": "fbnic",
"PathPrefixes": [
"tools/",
"arch/",
"net/"
]
}Results: {
"error": "no matches"
} |
| 23/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35281 output: 19 thoughts: 40 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, and delivered as a first-person summary: **Digging Deeper: The `fbnic` Hunt** Alright, so the initial search across the standard suspects – tools, architecture-specific code, and networking subdirectories – yielded nothing directly linked to 'fbnic'. That's a little surprising, but not entirely unexpected. Now, my immediate thought is: where else might this piece of potentially critical code be lurking within the kernel? Given that our primary focus has thus far been `drivers/net/ethernet/meta/`, my next move is clear. I need to widen the scope of the search. I need to check the entire kernel source, specifically looking for any instances of `fbnic`. It's a bit of a broad sweep, sure, but sometimes these things can pop up in unexpected locations, perhaps as part of a more generic driver or subsystem. I'm thinking, "Let's see what else the kernel has to say about `fbnic` before drawing any conclusions". This will reveal if `fbnic` is referenced or used elsewhere in the kernel code. |
| 24/2 | 2026/10/15 03:25 | tool | grepper |
0mArgs:{
"Expression": "CONFIG_FBNIC"
}Results: {
"Output": "drivers/net/ethernet/meta/Makefile-5-\ndrivers/net/ethernet/meta/Makefile:6:obj-$(CONFIG_FBNIC) += fbnic/\ndrivers/net/ethernet/meta/Makefile-7-obj-$(CONFIG_MPNIC) += mpnic/\n--\ndrivers/net/ethernet/meta/fbnic/Makefile-7-\ndrivers/net/ethernet/meta/fbnic/Makefile:8:obj-$(CONFIG_FBNIC) += fbnic.o\ndrivers/net/ethernet/meta/fbnic/Makefile-9-\n"
} |
| 25/2 | 2026/10/15 03:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35728 output: 94 thoughts: 510 Thoughts: **WorthFuzzing Assessment: fbnic Driver Update** Okay, here's the breakdown of my analysis. Looking at the diff, it's pretty straightforward. All the modified files are neatly contained within `drivers/net/ethernet/meta/fbnic/`: `fbnic.h`, `fbnic_fw.c`, `fbnic_fw.h`, `fbnic_hwmon.c`, `fbnic_mac.c`, and `fbnic_mac.h`. The changes center around adding hardware monitoring (hwmon) caching and alarm notification for thermal and voltage sensors, read directly from the firmware mailbox of Meta's fbnic PCIe ASIC NIC. Now, the crucial point: this fbnic NIC is *definitely* tied to specific hardware. It's a proprietary PCIe ASIC, and the driver requires that physical hardware to function. It's *not* emulated in standard environments like QEMU or typical virtualized setups. Let me verify that I am making the right call... Okay, going through the instructions again confirms it: "Structurally unreachable hardware: * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU". Yep, that's this, and it fits perfectly. Therefore, `WorthFuzzing` has to be `false` here. The code is inherently unreachable for fuzzing, which means the fuzzer won't be able to hit any of the modified code paths. I'm going to set `EnableConfigs` to an empty list, `FocusSymbols` to an empty list, and the `Reasoning` should be a concise summary: "The patch only touches the fbnic driver (`drivers/net/ethernet/meta/fbnic/`), which is a driver for Meta's proprietary PCIe network interface card (ASIC) that requires physical hardware not emulated in standard QEMU/virtualized environments. Thus, the modified code is structurally unreachable for fuzzing." Just a quick sanity check to ensure I am calling `set-results` correctly: `EnableConfigs` should be null or a list of strings, `FocusSymbols` should also be null or a list of strings, `Reasoning` is a string, and of course, `WorthFuzzing` is a boolean. Okay, let's call `set-results`. |
| 26/2 | 2026/10/15 03:25 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies the fbnic driver (drivers/net/ethernet/meta/fbnic/), which supports Meta's custom PCIe Host Network Interface ASIC. This driver requires physical PCIe hardware not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies the fbnic driver (drivers/net/ethernet/meta/fbnic/), which supports Meta's custom PCIe Host Network Interface ASIC. This driver requires physical PCIe hardware not emulated in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
} |
| 27/1 | 2026/10/15 03:25 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|