| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/04 23:17 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies Intel Ethernet drivers (i40e, iavf, ice, igc). These are drivers for physical PCIe hardware cards that are not emulated in standard QEMU. Furthermore, these drivers typically require complex interactions with hardware firmware (e.g., AdminQ) during probe, meaning they cannot be successfully initialized or reached via generic PCI fuzzing in virtualized environments. Therefore, the modified code paths are unreachable during fuzzing.",
"WorthFuzzing": false
} |
| 1/1 | 2026/08/04 23:17 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 25e113a4a33351336fd530d388d9888167c10293\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Aug 4 23:17:12 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex a04683004a567..4f0f7626605ba 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -6907,7 +6907,7 @@ static int i40e_hw_set_dcb_config(struct i40e_pf *pf,\n \tint ret;\n \n \t/* Check if need reconfiguration */\n-\tif (!memcmp(\u0026new_cfg, \u0026old_cfg, sizeof(new_cfg))) {\n+\tif (!memcmp(new_cfg, old_cfg, sizeof(*new_cfg))) {\n \t\tdev_dbg(\u0026pf-\u003epdev-\u003edev, \"No Change in DCB Config required.\\n\");\n \t\treturn 0;\n \t}\n@@ -14494,13 +14494,15 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,\n \tif (vsi-\u003enetdev_registered) {\n \t\tvsi-\u003enetdev_registered = false;\n \t\tunregister_netdev(vsi-\u003enetdev);\n-\t\tfree_netdev(vsi-\u003enetdev);\n-\t\tvsi-\u003enetdev = NULL;\n \t}\n err_dl_port:\n \tif (vsi-\u003etype == I40E_VSI_MAIN)\n \t\ti40e_devlink_destroy_port(pf);\n err_netdev:\n+\tif (vsi-\u003enetdev) {\n+\t\tfree_netdev(vsi-\u003enetdev);\n+\t\tvsi-\u003enetdev = NULL;\n+\t}\n \ti40e_aq_delete_element(\u0026pf-\u003ehw, vsi-\u003eseid, NULL);\n err_vsi:\n \ti40e_vsi_clear(vsi);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\nindex a26c3d47ec156..0cc434b26eb88 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c\n@@ -4943,6 +4943,23 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable)\n \treturn ret;\n }\n \n+/**\n+ * i40e_setup_vf_trust - Enable/disable VF trust mode without reset\n+ * @vf: VF to configure\n+ * @setting: trust setting\n+ *\n+ * Update VF flags when changing trust without performing a VF reset.\n+ * This is only called when it's safe to skip the reset (VF has no advanced\n+ * features configured that need cleanup).\n+ */\n+static void i40e_setup_vf_trust(struct i40e_vf *vf, bool setting)\n+{\n+\tif (setting)\n+\t\tset_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, \u0026vf-\u003evf_caps);\n+\telse\n+\t\tclear_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, \u0026vf-\u003evf_caps);\n+}\n+\n /**\n * i40e_ndo_set_vf_trust\n * @netdev: network interface device structure of the pf\n@@ -4987,19 +5004,20 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)\n \tset_bit(__I40E_MACVLAN_SYNC_PENDING, pf-\u003estate);\n \tpf-\u003evsi[vf-\u003elan_vsi_idx]-\u003eflags |= I40E_VSI_FLAG_FILTER_CHANGED;\n \n-\ti40e_vc_reset_vf(vf, true);\n+\t/* Reset only if revoking trust and VF has advanced features configured */\n+\tif (!setting \u0026\u0026\n+\t (vf-\u003eadq_enabled || vf-\u003enum_cloud_filters \u003e 0 ||\n+\t test_bit(I40E_VF_STATE_UC_PROMISC, \u0026vf-\u003evf_states) ||\n+\t test_bit(I40E_VF_STATE_MC_PROMISC, \u0026vf-\u003evf_states))) {\n+\t\ti40e_vc_reset_vf(vf, true);\n+\t\ti40e_del_all_cloud_filters(vf);\n+\t} else {\n+\t\ti40e_setup_vf_trust(vf, setting);\n+\t}\n+\n \tdev_info(\u0026pf-\u003epdev-\u003edev, \"VF %u is now %strusted\\n\",\n \t\t vf_id, setting ? \"\" : \"un\");\n \n-\tif (vf-\u003eadq_enabled) {\n-\t\tif (!vf-\u003etrusted) {\n-\t\t\tdev_info(\u0026pf-\u003epdev-\u003edev,\n-\t\t\t\t \"VF %u no longer Trusted, deleting all cloud filters\\n\",\n-\t\t\t\t vf_id);\n-\t\t\ti40e_del_all_cloud_filters(vf);\n-\t\t}\n-\t}\n-\n out:\n \tclear_bit(__I40E_VIRTCHNL_OP_PENDING, pf-\u003estate);\n \treturn ret;\ndiff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h\nindex 050f8241ef5e6..5fcbfa0ca8553 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf.h\n+++ b/drivers/net/ethernet/intel/iavf/iavf.h\n@@ -259,7 +259,6 @@ struct iavf_adapter {\n \tstruct work_struct adminq_task;\n \tstruct work_struct finish_config;\n \twait_queue_head_t down_waitqueue;\n-\twait_queue_head_t vc_waitqueue;\n \tstruct iavf_q_vector *q_vectors;\n \tstruct list_head vlan_filter_list;\n \tint num_vlan_filters;\n@@ -588,8 +587,9 @@ void iavf_configure_queues(struct iavf_adapter *adapter);\n void iavf_enable_queues(struct iavf_adapter *adapter);\n void iavf_disable_queues(struct iavf_adapter *adapter);\n void iavf_map_queues(struct iavf_adapter *adapter);\n-void iavf_add_ether_addrs(struct iavf_adapter *adapter);\n+int iavf_add_ether_addrs(struct iavf_adapter *adapter);\n void iavf_del_ether_addrs(struct iavf_adapter *adapter);\n+void iavf_mac_add_reject(struct iavf_adapter *adapter);\n void iavf_add_vlans(struct iavf_adapter *adapter);\n void iavf_del_vlans(struct iavf_adapter *adapter);\n void iavf_set_promiscuous(struct iavf_adapter *adapter);\n@@ -606,6 +606,13 @@ void iavf_disable_vlan_stripping(struct iavf_adapter *adapter);\n void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t\t\t enum virtchnl_ops v_opcode,\n \t\t\t enum iavf_status v_retval, u8 *msg, u16 msglen);\n+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,\n+\t\t\t\tstruct iavf_arq_event_info *event,\n+\t\t\t\tbool (*condition)(struct iavf_adapter *adapter,\n+\t\t\t\t\t\t const void *data,\n+\t\t\t\t\t\t enum virtchnl_ops v_op),\n+\t\t\t\tconst void *cond_data,\n+\t\t\t\tunsigned int timeout_ms);\n int iavf_config_rss(struct iavf_adapter *adapter);\n void iavf_cfg_queues_bw(struct iavf_adapter *adapter);\n void iavf_cfg_queues_quanta_size(struct iavf_adapter *adapter);\ndiff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c\nindex 29b8403a066bc..3fa288e3798ae 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf_main.c\n+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c\n@@ -1029,6 +1029,60 @@ static bool iavf_is_mac_set_handled(struct net_device *netdev,\n \treturn ret;\n }\n \n+/**\n+ * iavf_mac_change_done - Check if MAC change completed\n+ * @adapter: board private structure\n+ * @data: MAC address being checked (as const void *)\n+ * @v_op: virtchnl opcode from processed message\n+ *\n+ * Callback for iavf_poll_virtchnl_response() to check if MAC change completed.\n+ *\n+ * Return: true if MAC change completed, false otherwise\n+ */\n+static bool iavf_mac_change_done(struct iavf_adapter *adapter,\n+\t\t\t\t const void *data, enum virtchnl_ops v_op)\n+{\n+\tconst u8 *addr = data;\n+\n+\treturn iavf_is_mac_set_handled(adapter-\u003enetdev, addr);\n+}\n+\n+/**\n+ * iavf_set_mac_sync - Synchronously change MAC address\n+ * @adapter: board private structure\n+ * @addr: MAC address to set\n+ *\n+ * Send MAC change request to PF and poll admin queue for response.\n+ * Caller must hold netdev_lock. This can sleep for up to 2.5 seconds.\n+ * Event buffer is allocated before sending to avoid state mismatch if\n+ * allocation fails after message is sent to PF.\n+ *\n+ * Return: 0 on success, negative on failure\n+ */\n+static int iavf_set_mac_sync(struct iavf_adapter *adapter, const u8 *addr)\n+{\n+\tstruct iavf_arq_event_info event;\n+\tint ret;\n+\n+\tnetdev_assert_locked(adapter-\u003enetdev);\n+\n+\tevent.buf_len = IAVF_MAX_AQ_BUF_SIZE;\n+\tevent.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);\n+\tif (!event.msg_buf)\n+\t\treturn -ENOMEM;\n+\n+\tret = iavf_add_ether_addrs(adapter);\n+\tif (ret)\n+\t\tgoto out;\n+\n+\tret = iavf_poll_virtchnl_response(adapter, \u0026event,\n+\t\t\t\t\t iavf_mac_change_done, addr, 2500);\n+\n+out:\n+\tkfree(event.msg_buf);\n+\treturn ret;\n+}\n+\n /**\n * iavf_set_mac - NDO callback to set port MAC address\n * @netdev: network interface device structure\n@@ -1042,29 +1096,30 @@ static int iavf_set_mac(struct net_device *netdev, void *p)\n \tstruct sockaddr *addr = p;\n \tint ret;\n \n+\tif (iavf_is_reset_in_progress(adapter) || adapter-\u003estate \u003c __IAVF_DOWN)\n+\t\treturn -EBUSY;\n+\n \tif (!is_valid_ether_addr(addr-\u003esa_data))\n \t\treturn -EADDRNOTAVAIL;\n \n \tret = iavf_replace_primary_mac(adapter, addr-\u003esa_data);\n-\n \tif (ret)\n \t\treturn ret;\n \n-\tret = wait_event_interruptible_timeout(adapter-\u003evc_waitqueue,\n-\t\t\t\t\t iavf_is_mac_set_handled(netdev, addr-\u003esa_data),\n-\t\t\t\t\t msecs_to_jiffies(2500));\n-\n-\t/* If ret \u003c 0 then it means wait was interrupted.\n-\t * If ret == 0 then it means we got a timeout.\n-\t * else it means we got response for set MAC from PF,\n-\t * check if netdev MAC was updated to requested MAC,\n-\t * if yes then set MAC succeeded otherwise it failed return -EACCES\n-\t */\n-\tif (ret \u003c 0)\n+\tret = iavf_set_mac_sync(adapter, addr-\u003esa_data);\n+\tif (ret) {\n+\t\t/* Rollback only if send failed (message never reached PF).\n+\t\t * Don't rollback on timeout (-EAGAIN) because the message was\n+\t\t * sent and PF will eventually respond. When the response arrives,\n+\t\t * iavf_virtchnl_completion() will handle rollback (on PF error)\n+\t\t * or acceptance (on PF success) automatically.\n+\t\t */\n+\t\tif (ret != -EAGAIN) {\n+\t\t\tiavf_mac_add_reject(adapter);\n+\t\t\tether_addr_copy(adapter-\u003ehw.mac.addr, netdev-\u003edev_addr);\n+\t\t}\n \t\treturn ret;\n-\n-\tif (!ret)\n-\t\treturn -EAGAIN;\n+\t}\n \n \tif (!ether_addr_equal(netdev-\u003edev_addr, addr-\u003esa_data))\n \t\treturn -EACCES;\n@@ -5394,9 +5449,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t/* Setup the wait queue for indicating transition to down status */\n \tinit_waitqueue_head(\u0026adapter-\u003edown_waitqueue);\n \n-\t/* Setup the wait queue for indicating virtchannel events */\n-\tinit_waitqueue_head(\u0026adapter-\u003evc_waitqueue);\n-\n \tINIT_LIST_HEAD(\u0026adapter-\u003eptp.aq_cmds);\n \tinit_waitqueue_head(\u0026adapter-\u003eptp.phc_time_waitqueue);\n \tmutex_init(\u0026adapter-\u003eptp.aq_cmd_lock);\ndiff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\nindex ec234cc8bd9db..e6b7e8f82c7c1 100644\n--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\n+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c\n@@ -2,6 +2,7 @@\n /* Copyright(c) 2013 - 2018 Intel Corporation. */\n \n #include \u003clinux/net/intel/libie/rx.h\u003e\n+#include \u003cnet/netdev_lock.h\u003e\n \n #include \"iavf.h\"\n #include \"iavf_ptp.h\"\n@@ -555,20 +556,23 @@ iavf_set_mac_addr_type(struct virtchnl_ether_addr *virtchnl_ether_addr,\n * @adapter: adapter structure\n *\n * Request that the PF add one or more addresses to our filters.\n- **/\n-void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n+ *\n+ * Return: 0 on success, negative on failure\n+ */\n+int iavf_add_ether_addrs(struct iavf_adapter *adapter)\n {\n \tstruct virtchnl_ether_addr_list *veal;\n \tstruct iavf_mac_filter *f;\n \tint i = 0, count = 0;\n \tbool more = false;\n \tsize_t len;\n+\tint ret;\n \n \tif (adapter-\u003ecurrent_op != VIRTCHNL_OP_UNKNOWN) {\n \t\t/* bail because we already have a command pending */\n \t\tdev_err(\u0026adapter-\u003epdev-\u003edev, \"Cannot add filters, command %d pending\\n\",\n \t\t\tadapter-\u003ecurrent_op);\n-\t\treturn;\n+\t\treturn -EBUSY;\n \t}\n \n \tspin_lock_bh(\u0026adapter-\u003emac_vlan_list_lock);\n@@ -580,7 +584,7 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \tif (!count) {\n \t\tadapter-\u003eaq_required \u0026= ~IAVF_FLAG_AQ_ADD_MAC_FILTER;\n \t\tspin_unlock_bh(\u0026adapter-\u003emac_vlan_list_lock);\n-\t\treturn;\n+\t\treturn 0;\n \t}\n \tadapter-\u003ecurrent_op = VIRTCHNL_OP_ADD_ETH_ADDR;\n \n@@ -594,8 +598,9 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \n \tveal = kzalloc(len, GFP_ATOMIC);\n \tif (!veal) {\n+\t\tadapter-\u003ecurrent_op = VIRTCHNL_OP_UNKNOWN;\n \t\tspin_unlock_bh(\u0026adapter-\u003emac_vlan_list_lock);\n-\t\treturn;\n+\t\treturn -ENOMEM;\n \t}\n \n \tveal-\u003evsi_id = adapter-\u003evsi_res-\u003evsi_id;\n@@ -615,8 +620,15 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)\n \n \tspin_unlock_bh(\u0026adapter-\u003emac_vlan_list_lock);\n \n-\tiavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);\n+\tret = iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);\n \tkfree(veal);\n+\tif (ret) {\n+\t\tdev_err(\u0026adapter-\u003epdev-\u003edev,\n+\t\t\t\"Unable to send ADD_ETH_ADDR message to PF, error %d\\n\", ret);\n+\t\tadapter-\u003ecurrent_op = VIRTCHNL_OP_UNKNOWN;\n+\t}\n+\n+\treturn ret;\n }\n \n /**\n@@ -712,8 +724,8 @@ static void iavf_mac_add_ok(struct iavf_adapter *adapter)\n * @adapter: adapter structure\n *\n * Remove filters from list based on PF response.\n- **/\n-static void iavf_mac_add_reject(struct iavf_adapter *adapter)\n+ */\n+void iavf_mac_add_reject(struct iavf_adapter *adapter)\n {\n \tstruct net_device *netdev = adapter-\u003enetdev;\n \tstruct iavf_mac_filter *f, *ftmp;\n@@ -2364,7 +2376,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t\t\tiavf_mac_add_reject(adapter);\n \t\t\t/* restore administratively set MAC address */\n \t\t\tether_addr_copy(adapter-\u003ehw.mac.addr, netdev-\u003edev_addr);\n-\t\t\twake_up(\u0026adapter-\u003evc_waitqueue);\n \t\t\tbreak;\n \t\tcase VIRTCHNL_OP_DEL_ETH_ADDR:\n \t\t\tdev_err(\u0026adapter-\u003epdev-\u003edev, \"Failed to delete MAC filter, error %s\\n\",\n@@ -2555,7 +2566,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t\t\teth_hw_addr_set(netdev, adapter-\u003ehw.mac.addr);\n \t\t\tnetif_addr_unlock_bh(netdev);\n \t\t}\n-\t\twake_up(\u0026adapter-\u003evc_waitqueue);\n \t\tbreak;\n \tcase VIRTCHNL_OP_GET_STATS: {\n \t\tstruct iavf_eth_stats *stats =\n@@ -2950,3 +2960,72 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,\n \t} /* switch v_opcode */\n \tadapter-\u003ecurrent_op = VIRTCHNL_OP_UNKNOWN;\n }\n+\n+/**\n+ * iavf_poll_virtchnl_response - Poll admin queue for virtchnl response\n+ * @adapter: adapter structure\n+ * @event: pre-allocated event buffer to use for polling\n+ * @condition: callback to check if desired response received\n+ * @cond_data: context data passed to condition callback\n+ * @timeout_ms: maximum time to wait in milliseconds\n+ *\n+ * Polls the admin queue and processes all incoming virtchnl messages.\n+ * After processing each valid message, calls the condition callback to check\n+ * if the expected response has been received. The callback receives the opcode\n+ * of the processed message to identify which response was received. Continues\n+ * polling until the callback returns true or timeout expires.\n+ *\n+ * Caller must allocate event buffer before sending any messages to PF to avoid\n+ * state mismatch if allocation fails after message is sent.\n+ *\n+ * Caller must hold netdev_lock. This can sleep for up to timeout_ms while\n+ * polling hardware.\n+ *\n+ * Return: 0 on success (condition met), -EAGAIN on timeout, or error code\n+ */\n+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,\n+\t\t\t\tstruct iavf_arq_event_info *event,\n+\t\t\t\tbool (*condition)(struct iavf_adapter *adapter,\n+\t\t\t\t\t\t const void *data,\n+\t\t\t\t\t\t enum virtchnl_ops v_op),\n+\t\t\t\tconst void *cond_data,\n+\t\t\t\tunsigned int timeout_ms)\n+{\n+\tstruct iavf_hw *hw = \u0026adapter-\u003ehw;\n+\tenum virtchnl_ops received_op;\n+\tunsigned long timeout;\n+\tint ret = -EAGAIN;\n+\tu16 pending = 0;\n+\tu32 v_retval;\n+\n+\tnetdev_assert_locked(adapter-\u003enetdev);\n+\n+\ttimeout = jiffies + msecs_to_jiffies(timeout_ms);\n+\tdo {\n+\t\tif (!pending)\n+\t\t\tusleep_range(50, 75);\n+\n+\t\tif (iavf_clean_arq_element(hw, event, \u0026pending) == IAVF_SUCCESS) {\n+\t\t\treceived_op = (enum virtchnl_ops)le32_to_cpu(event-\u003edesc.cookie_high);\n+\t\t\tif (received_op != VIRTCHNL_OP_UNKNOWN) {\n+\t\t\t\tv_retval = le32_to_cpu(event-\u003edesc.cookie_low);\n+\n+\t\t\t\tiavf_virtchnl_completion(adapter, received_op,\n+\t\t\t\t\t\t\t (enum iavf_status)v_retval,\n+\t\t\t\t\t\t\t event-\u003emsg_buf, event-\u003emsg_len);\n+\n+\t\t\t\tif (condition(adapter, cond_data, received_op)) {\n+\t\t\t\t\tret = 0;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\tmemset(event-\u003emsg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);\n+\n+\t\t\tif (pending)\n+\t\t\t\tcontinue;\n+\t\t}\n+\t} while (time_before(jiffies, timeout));\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex fc91b6665f905..83da5ba6eeb17 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -328,6 +328,8 @@ enum ice_vsi_state {\n struct ice_vsi_stats {\n \tstruct ice_ring_stats **tx_ring_stats; /* Tx ring stats array */\n \tstruct ice_ring_stats **rx_ring_stats; /* Rx ring stats array */\n+\tu16 tx_ring_stats_len;\n+\tu16 rx_ring_stats_len;\n };\n \n /* struct that defines a VSI, associated with a dev */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c\nindex b069e6c514fb1..6e7bba4738989 100644\n--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c\n+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c\n@@ -95,7 +95,7 @@ ice_eswitch_release_repr(struct ice_pf *pf, struct ice_repr *repr)\n \t\treturn;\n \n \tice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);\n-\tmetadata_dst_free(repr-\u003edst);\n+\tdst_release(\u0026repr-\u003edst-\u003edst);\n \trepr-\u003edst = NULL;\n \tice_fltr_add_mac_and_broadcast(vsi, repr-\u003eparent_mac,\n \t\t\t\t ICE_FWD_TO_VSI);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c\nindex 8cdc4fda89e97..c71849119d04e 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_lib.c\n@@ -338,7 +338,6 @@ static void ice_vsi_free_stats(struct ice_vsi *vsi)\n {\n \tstruct ice_vsi_stats *vsi_stat;\n \tstruct ice_pf *pf = vsi-\u003eback;\n-\tint i;\n \n \tif (vsi-\u003etype == ICE_VSI_CHNL)\n \t\treturn;\n@@ -349,14 +348,14 @@ static void ice_vsi_free_stats(struct ice_vsi *vsi)\n \tif (!vsi_stat)\n \t\treturn;\n \n-\tice_for_each_alloc_txq(vsi, i) {\n+\tfor (int i = 0; i \u003c vsi_stat-\u003etx_ring_stats_len; i++) {\n \t\tif (vsi_stat-\u003etx_ring_stats[i]) {\n \t\t\tkfree_rcu(vsi_stat-\u003etx_ring_stats[i], rcu);\n \t\t\tWRITE_ONCE(vsi_stat-\u003etx_ring_stats[i], NULL);\n \t\t}\n \t}\n \n-\tice_for_each_alloc_rxq(vsi, i) {\n+\tfor (int i = 0; i \u003c vsi_stat-\u003erx_ring_stats_len; i++) {\n \t\tif (vsi_stat-\u003erx_ring_stats[i]) {\n \t\t\tkfree_rcu(vsi_stat-\u003erx_ring_stats[i], rcu);\n \t\t\tWRITE_ONCE(vsi_stat-\u003erx_ring_stats[i], NULL);\n@@ -513,51 +512,6 @@ static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)\n \treturn IRQ_HANDLED;\n }\n \n-/**\n- * ice_vsi_alloc_stat_arrays - Allocate statistics arrays\n- * @vsi: VSI pointer\n- */\n-static int ice_vsi_alloc_stat_arrays(struct ice_vsi *vsi)\n-{\n-\tstruct ice_vsi_stats *vsi_stat;\n-\tstruct ice_pf *pf = vsi-\u003eback;\n-\n-\tif (vsi-\u003etype == ICE_VSI_CHNL)\n-\t\treturn 0;\n-\tif (!pf-\u003evsi_stats)\n-\t\treturn -ENOENT;\n-\n-\tif (pf-\u003evsi_stats[vsi-\u003eidx])\n-\t/* realloc will happen in rebuild path */\n-\t\treturn 0;\n-\n-\tvsi_stat = kzalloc_obj(*vsi_stat);\n-\tif (!vsi_stat)\n-\t\treturn -ENOMEM;\n-\n-\tvsi_stat-\u003etx_ring_stats =\n-\t\tkzalloc_objs(*vsi_stat-\u003etx_ring_stats, vsi-\u003ealloc_txq);\n-\tif (!vsi_stat-\u003etx_ring_stats)\n-\t\tgoto err_alloc_tx;\n-\n-\tvsi_stat-\u003erx_ring_stats =\n-\t\tkzalloc_objs(*vsi_stat-\u003erx_ring_stats, vsi-\u003ealloc_rxq);\n-\tif (!vsi_stat-\u003erx_ring_stats)\n-\t\tgoto err_alloc_rx;\n-\n-\tpf-\u003evsi_stats[vsi-\u003eidx] = vsi_stat;\n-\n-\treturn 0;\n-\n-err_alloc_rx:\n-\tkfree(vsi_stat-\u003erx_ring_stats);\n-err_alloc_tx:\n-\tkfree(vsi_stat-\u003etx_ring_stats);\n-\tkfree(vsi_stat);\n-\tpf-\u003evsi_stats[vsi-\u003eidx] = NULL;\n-\treturn -ENOMEM;\n-}\n-\n /**\n * ice_vsi_alloc_def - set default values for already allocated VSI\n * @vsi: ptr to VSI\n@@ -2303,6 +2257,85 @@ static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)\n \treturn 0;\n }\n \n+/**\n+ * ice_vsi_realloc_stat_arrays - Frees unused stat structures or alloc new ones\n+ * @vsi: VSI pointer\n+ * Return: 0 on success or -ENOMEM on allocation failure.\n+ */\n+static int ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)\n+{\n+\tu16 req_txq = vsi-\u003ereq_txq ? vsi-\u003ereq_txq : vsi-\u003ealloc_txq;\n+\tu16 req_rxq = vsi-\u003ereq_rxq ? vsi-\u003ereq_rxq : vsi-\u003ealloc_rxq;\n+\tstruct ice_ring_stats **tx_ring_stats;\n+\tstruct ice_ring_stats **rx_ring_stats;\n+\tstruct ice_vsi_stats *vsi_stat;\n+\tstruct ice_pf *pf = vsi-\u003eback;\n+\tu16 prev_txq, prev_rxq;\n+\n+\tif (vsi-\u003etype == ICE_VSI_CHNL)\n+\t\treturn 0;\n+\n+\tvsi_stat = pf-\u003evsi_stats[vsi-\u003eidx];\n+\tif (!vsi_stat) {\n+\t\tvsi_stat = kzalloc_obj(*vsi_stat);\n+\t\tif (!vsi_stat)\n+\t\t\treturn -ENOMEM;\n+\t}\n+\n+\tprev_txq = vsi_stat-\u003etx_ring_stats_len;\n+\tif (req_txq \u003c prev_txq) {\n+\t\tfor (int i = req_txq; i \u003c prev_txq; i++) {\n+\t\t\tif (vsi_stat-\u003etx_ring_stats[i]) {\n+\t\t\t\tkfree_rcu(vsi_stat-\u003etx_ring_stats[i], rcu);\n+\t\t\t\tWRITE_ONCE(vsi_stat-\u003etx_ring_stats[i], NULL);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\ttx_ring_stats = vsi_stat-\u003etx_ring_stats;\n+\tvsi_stat-\u003etx_ring_stats =\n+\t\tkrealloc_array(vsi_stat-\u003etx_ring_stats, req_txq,\n+\t\t\t sizeof(*vsi_stat-\u003etx_ring_stats),\n+\t\t\t GFP_KERNEL | __GFP_ZERO);\n+\tif (!vsi_stat-\u003etx_ring_stats) {\n+\t\tvsi_stat-\u003etx_ring_stats = tx_ring_stats;\n+\t\tgoto err_free_partial_vsi_stat;\n+\t}\n+\tvsi_stat-\u003etx_ring_stats_len = req_txq;\n+\n+\tprev_rxq = vsi_stat-\u003erx_ring_stats_len;\n+\tif (req_rxq \u003c prev_rxq) {\n+\t\tfor (int i = req_rxq; i \u003c prev_rxq; i++) {\n+\t\t\tif (vsi_stat-\u003erx_ring_stats[i]) {\n+\t\t\t\tkfree_rcu(vsi_stat-\u003erx_ring_stats[i], rcu);\n+\t\t\t\tWRITE_ONCE(vsi_stat-\u003erx_ring_stats[i], NULL);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trx_ring_stats = vsi_stat-\u003erx_ring_stats;\n+\tvsi_stat-\u003erx_ring_stats =\n+\t\tkrealloc_array(vsi_stat-\u003erx_ring_stats, req_rxq,\n+\t\t\t sizeof(*vsi_stat-\u003erx_ring_stats),\n+\t\t\t GFP_KERNEL | __GFP_ZERO);\n+\tif (!vsi_stat-\u003erx_ring_stats) {\n+\t\tvsi_stat-\u003erx_ring_stats = rx_ring_stats;\n+\t\tgoto err_free_partial_vsi_stat;\n+\t}\n+\tvsi_stat-\u003erx_ring_stats_len = req_rxq;\n+\n+\tpf-\u003evsi_stats[vsi-\u003eidx] = vsi_stat;\n+\treturn 0;\n+\n+err_free_partial_vsi_stat:\n+\tif (!pf-\u003evsi_stats[vsi-\u003eidx]) {\n+\t\t/* vsi_stat was not visible before current alloc attempt */\n+\t\tkfree(vsi_stat-\u003etx_ring_stats);\n+\t\tkfree(vsi_stat);\n+\t}\n+\treturn -ENOMEM;\n+}\n+\n /**\n * ice_vsi_cfg_def - configure default VSI based on the type\n * @vsi: pointer to VSI\n@@ -2320,7 +2353,7 @@ static int ice_vsi_cfg_def(struct ice_vsi *vsi)\n \t\treturn ret;\n \n \t/* allocate memory for Tx/Rx ring stat pointers */\n-\tret = ice_vsi_alloc_stat_arrays(vsi);\n+\tret = ice_vsi_realloc_stat_arrays(vsi);\n \tif (ret)\n \t\tgoto unroll_vsi_alloc;\n \n@@ -3011,66 +3044,6 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,\n \t}\n }\n \n-/**\n- * ice_vsi_realloc_stat_arrays - Frees unused stat structures or alloc new ones\n- * @vsi: VSI pointer\n- */\n-static int\n-ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)\n-{\n-\tu16 req_txq = vsi-\u003ereq_txq ? vsi-\u003ereq_txq : vsi-\u003ealloc_txq;\n-\tu16 req_rxq = vsi-\u003ereq_rxq ? vsi-\u003ereq_rxq : vsi-\u003ealloc_rxq;\n-\tstruct ice_ring_stats **tx_ring_stats;\n-\tstruct ice_ring_stats **rx_ring_stats;\n-\tstruct ice_vsi_stats *vsi_stat;\n-\tstruct ice_pf *pf = vsi-\u003eback;\n-\tu16 prev_txq = vsi-\u003ealloc_txq;\n-\tu16 prev_rxq = vsi-\u003ealloc_rxq;\n-\tint i;\n-\n-\tvsi_stat = pf-\u003evsi_stats[vsi-\u003eidx];\n-\n-\tif (req_txq \u003c prev_txq) {\n-\t\tfor (i = req_txq; i \u003c prev_txq; i++) {\n-\t\t\tif (vsi_stat-\u003etx_ring_stats[i]) {\n-\t\t\t\tkfree_rcu(vsi_stat-\u003etx_ring_stats[i], rcu);\n-\t\t\t\tWRITE_ONCE(vsi_stat-\u003etx_ring_stats[i], NULL);\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\ttx_ring_stats = vsi_stat-\u003etx_ring_stats;\n-\tvsi_stat-\u003etx_ring_stats =\n-\t\tkrealloc_array(vsi_stat-\u003etx_ring_stats, req_txq,\n-\t\t\t sizeof(*vsi_stat-\u003etx_ring_stats),\n-\t\t\t GFP_KERNEL | __GFP_ZERO);\n-\tif (!vsi_stat-\u003etx_ring_stats) {\n-\t\tvsi_stat-\u003etx_ring_stats = tx_ring_stats;\n-\t\treturn -ENOMEM;\n-\t}\n-\n-\tif (req_rxq \u003c prev_rxq) {\n-\t\tfor (i = req_rxq; i \u003c prev_rxq; i++) {\n-\t\t\tif (vsi_stat-\u003erx_ring_stats[i]) {\n-\t\t\t\tkfree_rcu(vsi_stat-\u003erx_ring_stats[i], rcu);\n-\t\t\t\tWRITE_ONCE(vsi_stat-\u003erx_ring_stats[i], NULL);\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\trx_ring_stats = vsi_stat-\u003erx_ring_stats;\n-\tvsi_stat-\u003erx_ring_stats =\n-\t\tkrealloc_array(vsi_stat-\u003erx_ring_stats, req_rxq,\n-\t\t\t sizeof(*vsi_stat-\u003erx_ring_stats),\n-\t\t\t GFP_KERNEL | __GFP_ZERO);\n-\tif (!vsi_stat-\u003erx_ring_stats) {\n-\t\tvsi_stat-\u003erx_ring_stats = rx_ring_stats;\n-\t\treturn -ENOMEM;\n-\t}\n-\n-\treturn 0;\n-}\n-\n /**\n * ice_vsi_rebuild - Rebuild VSI after reset\n * @vsi: VSI to be rebuild\ndiff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c\nindex e04de02155966..5589378998181 100644\n--- a/drivers/net/ethernet/intel/ice/ice_sriov.c\n+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c\n@@ -1366,6 +1366,23 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)\n \treturn __ice_set_vf_mac(ice_netdev_to_pf(netdev), vf_id, mac);\n }\n \n+/**\n+ * ice_setup_vf_trust - Enable/disable VF trust mode without reset\n+ * @vf: VF to configure\n+ * @setting: trust setting\n+ *\n+ * Update VF flags when changing trust without performing a VF reset.\n+ * This is only called when it's safe to skip the reset (VF has no advanced\n+ * features configured that need cleanup).\n+ */\n+static void ice_setup_vf_trust(struct ice_vf *vf, bool setting)\n+{\n+\tif (setting)\n+\t\tset_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, \u0026vf-\u003evf_caps);\n+\telse\n+\t\tclear_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, \u0026vf-\u003evf_caps);\n+}\n+\n /**\n * ice_set_vf_trust\n * @netdev: network interface device structure\n@@ -1401,11 +1418,19 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)\n \n \tmutex_lock(\u0026vf-\u003ecfg_lock);\n \n-\twhile (!trusted \u0026\u0026 vf-\u003enum_mac_lldp)\n-\t\tice_vf_update_mac_lldp_num(vf, ice_get_vf_vsi(vf), false);\n-\n-\tvf-\u003etrusted = trusted;\n-\tice_reset_vf(vf, ICE_VF_RESET_NOTIFY);\n+\t/* Reset only if revoking trust and VF has advanced features configured */\n+\tif (!trusted \u0026\u0026\n+\t (vf-\u003enum_mac_lldp \u003e 0 ||\n+\t test_bit(ICE_VF_STATE_UC_PROMISC, vf-\u003evf_states) ||\n+\t test_bit(ICE_VF_STATE_MC_PROMISC, vf-\u003evf_states))) {\n+\t\twhile (vf-\u003enum_mac_lldp)\n+\t\t\tice_vf_update_mac_lldp_num(vf, ice_get_vf_vsi(vf), false);\n+\t\tvf-\u003etrusted = trusted;\n+\t\tice_reset_vf(vf, ICE_VF_RESET_NOTIFY);\n+\t} else {\n+\t\tvf-\u003etrusted = trusted;\n+\t\tice_setup_vf_trust(vf, trusted);\n+\t}\n \tdev_info(ice_pf_to_dev(pf), \"VF %u is now %strusted\\n\",\n \t\t vf_id, trusted ? \"\" : \"un\");\n \ndiff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c\nindex 16fcc8cf61919..39043d8ca1bf4 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -7585,11 +7585,13 @@ static int __igc_resume(struct device *dev, bool rpm)\n \t\terr = __igc_open(netdev, true);\n \t\tif (!rpm)\n \t\t\trtnl_unlock();\n-\t\tif (!err)\n-\t\t\tnetif_device_attach(netdev);\n+\t\tif (err)\n+\t\t\treturn err;\n \t}\n \n-\treturn err;\n+\tnetif_device_attach(netdev);\n+\n+\treturn 0;\n }\n \n static int igc_resume(struct device *dev)\n"
} |
| 2/1 | 2026/08/04 23:17 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies Intel Ethernet drivers (i40e, iavf, ice, igc). These are drivers for physical PCIe hardware cards that are not emulated in standard QEMU. Furthermore, these drivers typically require complex interactions with hardware firmware (e.g., AdminQ) during probe, meaning they cannot be successfully initialized or reached via generic PCI fuzzing in virtualized environments. Therefore, the modified code paths are unreachable during fuzzing.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 25e113a4a33351336fd530d388d9888167c10293
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Aug 4 23:17:12 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index a04683004a567..4f0f7626605ba 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -6907,7 +6907,7 @@ static int i40e_hw_set_dcb_config(struct i40e_pf *pf,
int ret;
/* Check if need reconfiguration */
- if (!memcmp(&new_cfg, &old_cfg, sizeof(new_cfg))) {
+ if (!memcmp(new_cfg, old_cfg, sizeof(*new_cfg))) {
dev_dbg(&pf->pdev->dev, "No Change in DCB Config required.\n");
return 0;
}
@@ -14494,13 +14494,15 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
if (vsi->netdev_registered) {
vsi->netdev_registered = false;
unregister_netdev(vsi->netdev);
- free_netdev(vsi->netdev);
- vsi->netdev = NULL;
}
err_dl_port:
if (vsi->type == I40E_VSI_MAIN)
i40e_devlink_destroy_port(pf);
err_netdev:
+ if (vsi->netdev) {
+ free_netdev(vsi->netdev);
+ vsi->netdev = NULL;
+ }
i40e_aq_delete_element(&pf->hw, vsi->seid, NULL);
err_vsi:
i40e_vsi_clear(vsi);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index a26c3d47ec156..0cc434b26eb88 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -4943,6 +4943,23 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable)
return ret;
}
+/**
+ * i40e_setup_vf_trust - Enable/disable VF trust mode without reset
+ * @vf: VF to configure
+ * @setting: trust setting
+ *
+ * Update VF flags when changing trust without performing a VF reset.
+ * This is only called when it's safe to skip the reset (VF has no advanced
+ * features configured that need cleanup).
+ */
+static void i40e_setup_vf_trust(struct i40e_vf *vf, bool setting)
+{
+ if (setting)
+ set_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+ else
+ clear_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+}
+
/**
* i40e_ndo_set_vf_trust
* @netdev: network interface device structure of the pf
@@ -4987,19 +5004,20 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
set_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state);
pf->vsi[vf->lan_vsi_idx]->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
- i40e_vc_reset_vf(vf, true);
+ /* Reset only if revoking trust and VF has advanced features configured */
+ if (!setting &&
+ (vf->adq_enabled || vf->num_cloud_filters > 0 ||
+ test_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states) ||
+ test_bit(I40E_VF_STATE_MC_PROMISC, &vf->vf_states))) {
+ i40e_vc_reset_vf(vf, true);
+ i40e_del_all_cloud_filters(vf);
+ } else {
+ i40e_setup_vf_trust(vf, setting);
+ }
+
dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
vf_id, setting ? "" : "un");
- if (vf->adq_enabled) {
- if (!vf->trusted) {
- dev_info(&pf->pdev->dev,
- "VF %u no longer Trusted, deleting all cloud filters\n",
- vf_id);
- i40e_del_all_cloud_filters(vf);
- }
- }
-
out:
clear_bit(__I40E_VIRTCHNL_OP_PENDING, pf->state);
return ret;
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 050f8241ef5e6..5fcbfa0ca8553 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
+++ b/drivers/net/ethernet/intel/iavf/iavf.h
@@ -259,7 +259,6 @@ struct iavf_adapter {
struct work_struct adminq_task;
struct work_struct finish_config;
wait_queue_head_t down_waitqueue;
- wait_queue_head_t vc_waitqueue;
struct iavf_q_vector *q_vectors;
struct list_head vlan_filter_list;
int num_vlan_filters;
@@ -588,8 +587,9 @@ void iavf_configure_queues(struct iavf_adapter *adapter);
void iavf_enable_queues(struct iavf_adapter *adapter);
void iavf_disable_queues(struct iavf_adapter *adapter);
void iavf_map_queues(struct iavf_adapter *adapter);
-void iavf_add_ether_addrs(struct iavf_adapter *adapter);
+int iavf_add_ether_addrs(struct iavf_adapter *adapter);
void iavf_del_ether_addrs(struct iavf_adapter *adapter);
+void iavf_mac_add_reject(struct iavf_adapter *adapter);
void iavf_add_vlans(struct iavf_adapter *adapter);
void iavf_del_vlans(struct iavf_adapter *adapter);
void iavf_set_promiscuous(struct iavf_adapter *adapter);
@@ -606,6 +606,13 @@ void iavf_disable_vlan_stripping(struct iavf_adapter *adapter);
void iavf_virtchnl_completion(struct iavf_adapter *adapter,
enum virtchnl_ops v_opcode,
enum iavf_status v_retval, u8 *msg, u16 msglen);
+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,
+ struct iavf_arq_event_info *event,
+ bool (*condition)(struct iavf_adapter *adapter,
+ const void *data,
+ enum virtchnl_ops v_op),
+ const void *cond_data,
+ unsigned int timeout_ms);
int iavf_config_rss(struct iavf_adapter *adapter);
void iavf_cfg_queues_bw(struct iavf_adapter *adapter);
void iavf_cfg_queues_quanta_size(struct iavf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 29b8403a066bc..3fa288e3798ae 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -1029,6 +1029,60 @@ static bool iavf_is_mac_set_handled(struct net_device *netdev,
return ret;
}
+/**
+ * iavf_mac_change_done - Check if MAC change completed
+ * @adapter: board private structure
+ * @data: MAC address being checked (as const void *)
+ * @v_op: virtchnl opcode from processed message
+ *
+ * Callback for iavf_poll_virtchnl_response() to check if MAC change completed.
+ *
+ * Return: true if MAC change completed, false otherwise
+ */
+static bool iavf_mac_change_done(struct iavf_adapter *adapter,
+ const void *data, enum virtchnl_ops v_op)
+{
+ const u8 *addr = data;
+
+ return iavf_is_mac_set_handled(adapter->netdev, addr);
+}
+
+/**
+ * iavf_set_mac_sync - Synchronously change MAC address
+ * @adapter: board private structure
+ * @addr: MAC address to set
+ *
+ * Send MAC change request to PF and poll admin queue for response.
+ * Caller must hold netdev_lock. This can sleep for up to 2.5 seconds.
+ * Event buffer is allocated before sending to avoid state mismatch if
+ * allocation fails after message is sent to PF.
+ *
+ * Return: 0 on success, negative on failure
+ */
+static int iavf_set_mac_sync(struct iavf_adapter *adapter, const u8 *addr)
+{
+ struct iavf_arq_event_info event;
+ int ret;
+
+ netdev_assert_locked(adapter->netdev);
+
+ event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
+ event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
+ if (!event.msg_buf)
+ return -ENOMEM;
+
+ ret = iavf_add_ether_addrs(adapter);
+ if (ret)
+ goto out;
+
+ ret = iavf_poll_virtchnl_response(adapter, &event,
+ iavf_mac_change_done, addr, 2500);
+
+out:
+ kfree(event.msg_buf);
+ return ret;
+}
+
/**
* iavf_set_mac - NDO callback to set port MAC address
* @netdev: network interface device structure
@@ -1042,29 +1096,30 @@ static int iavf_set_mac(struct net_device *netdev, void *p)
struct sockaddr *addr = p;
int ret;
+ if (iavf_is_reset_in_progress(adapter) || adapter->state < __IAVF_DOWN)
+ return -EBUSY;
+
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
ret = iavf_replace_primary_mac(adapter, addr->sa_data);
-
if (ret)
return ret;
- ret = wait_event_interruptible_timeout(adapter->vc_waitqueue,
- iavf_is_mac_set_handled(netdev, addr->sa_data),
- msecs_to_jiffies(2500));
-
- /* If ret < 0 then it means wait was interrupted.
- * If ret == 0 then it means we got a timeout.
- * else it means we got response for set MAC from PF,
- * check if netdev MAC was updated to requested MAC,
- * if yes then set MAC succeeded otherwise it failed return -EACCES
- */
- if (ret < 0)
+ ret = iavf_set_mac_sync(adapter, addr->sa_data);
+ if (ret) {
+ /* Rollback only if send failed (message never reached PF).
+ * Don't rollback on timeout (-EAGAIN) because the message was
+ * sent and PF will eventually respond. When the response arrives,
+ * iavf_virtchnl_completion() will handle rollback (on PF error)
+ * or acceptance (on PF success) automatically.
+ */
+ if (ret != -EAGAIN) {
+ iavf_mac_add_reject(adapter);
+ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
+ }
return ret;
-
- if (!ret)
- return -EAGAIN;
+ }
if (!ether_addr_equal(netdev->dev_addr, addr->sa_data))
return -EACCES;
@@ -5394,9 +5449,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Setup the wait queue for indicating transition to down status */
init_waitqueue_head(&adapter->down_waitqueue);
- /* Setup the wait queue for indicating virtchannel events */
- init_waitqueue_head(&adapter->vc_waitqueue);
-
INIT_LIST_HEAD(&adapter->ptp.aq_cmds);
init_waitqueue_head(&adapter->ptp.phc_time_waitqueue);
mutex_init(&adapter->ptp.aq_cmd_lock);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index ec234cc8bd9db..e6b7e8f82c7c1 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2013 - 2018 Intel Corporation. */
#include <linux/net/intel/libie/rx.h>
+#include <net/netdev_lock.h>
#include "iavf.h"
#include "iavf_ptp.h"
@@ -555,20 +556,23 @@ iavf_set_mac_addr_type(struct virtchnl_ether_addr *virtchnl_ether_addr,
* @adapter: adapter structure
*
* Request that the PF add one or more addresses to our filters.
- **/
-void iavf_add_ether_addrs(struct iavf_adapter *adapter)
+ *
+ * Return: 0 on success, negative on failure
+ */
+int iavf_add_ether_addrs(struct iavf_adapter *adapter)
{
struct virtchnl_ether_addr_list *veal;
struct iavf_mac_filter *f;
int i = 0, count = 0;
bool more = false;
size_t len;
+ int ret;
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot add filters, command %d pending\n",
adapter->current_op);
- return;
+ return -EBUSY;
}
spin_lock_bh(&adapter->mac_vlan_list_lock);
@@ -580,7 +584,7 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)
if (!count) {
adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_MAC_FILTER;
spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
+ return 0;
}
adapter->current_op = VIRTCHNL_OP_ADD_ETH_ADDR;
@@ -594,8 +598,9 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)
veal = kzalloc(len, GFP_ATOMIC);
if (!veal) {
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
+ return -ENOMEM;
}
veal->vsi_id = adapter->vsi_res->vsi_id;
@@ -615,8 +620,15 @@ void iavf_add_ether_addrs(struct iavf_adapter *adapter)
spin_unlock_bh(&adapter->mac_vlan_list_lock);
- iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);
+ ret = iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)veal, len);
kfree(veal);
+ if (ret) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to send ADD_ETH_ADDR message to PF, error %d\n", ret);
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ }
+
+ return ret;
}
/**
@@ -712,8 +724,8 @@ static void iavf_mac_add_ok(struct iavf_adapter *adapter)
* @adapter: adapter structure
*
* Remove filters from list based on PF response.
- **/
-static void iavf_mac_add_reject(struct iavf_adapter *adapter)
+ */
+void iavf_mac_add_reject(struct iavf_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct iavf_mac_filter *f, *ftmp;
@@ -2364,7 +2376,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
iavf_mac_add_reject(adapter);
/* restore administratively set MAC address */
ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
- wake_up(&adapter->vc_waitqueue);
break;
case VIRTCHNL_OP_DEL_ETH_ADDR:
dev_err(&adapter->pdev->dev, "Failed to delete MAC filter, error %s\n",
@@ -2555,7 +2566,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
eth_hw_addr_set(netdev, adapter->hw.mac.addr);
netif_addr_unlock_bh(netdev);
}
- wake_up(&adapter->vc_waitqueue);
break;
case VIRTCHNL_OP_GET_STATS: {
struct iavf_eth_stats *stats =
@@ -2950,3 +2960,72 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
} /* switch v_opcode */
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
}
+
+/**
+ * iavf_poll_virtchnl_response - Poll admin queue for virtchnl response
+ * @adapter: adapter structure
+ * @event: pre-allocated event buffer to use for polling
+ * @condition: callback to check if desired response received
+ * @cond_data: context data passed to condition callback
+ * @timeout_ms: maximum time to wait in milliseconds
+ *
+ * Polls the admin queue and processes all incoming virtchnl messages.
+ * After processing each valid message, calls the condition callback to check
+ * if the expected response has been received. The callback receives the opcode
+ * of the processed message to identify which response was received. Continues
+ * polling until the callback returns true or timeout expires.
+ *
+ * Caller must allocate event buffer before sending any messages to PF to avoid
+ * state mismatch if allocation fails after message is sent.
+ *
+ * Caller must hold netdev_lock. This can sleep for up to timeout_ms while
+ * polling hardware.
+ *
+ * Return: 0 on success (condition met), -EAGAIN on timeout, or error code
+ */
+int iavf_poll_virtchnl_response(struct iavf_adapter *adapter,
+ struct iavf_arq_event_info *event,
+ bool (*condition)(struct iavf_adapter *adapter,
+ const void *data,
+ enum virtchnl_ops v_op),
+ const void *cond_data,
+ unsigned int timeout_ms)
+{
+ struct iavf_hw *hw = &adapter->hw;
+ enum virtchnl_ops received_op;
+ unsigned long timeout;
+ int ret = -EAGAIN;
+ u16 pending = 0;
+ u32 v_retval;
+
+ netdev_assert_locked(adapter->netdev);
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
+ do {
+ if (!pending)
+ usleep_range(50, 75);
+
+ if (iavf_clean_arq_element(hw, event, &pending) == IAVF_SUCCESS) {
+ received_op = (enum virtchnl_ops)le32_to_cpu(event->desc.cookie_high);
+ if (received_op != VIRTCHNL_OP_UNKNOWN) {
+ v_retval = le32_to_cpu(event->desc.cookie_low);
+
+ iavf_virtchnl_completion(adapter, received_op,
+ (enum iavf_status)v_retval,
+ event->msg_buf, event->msg_len);
+
+ if (condition(adapter, cond_data, received_op)) {
+ ret = 0;
+ break;
+ }
+ }
+
+ memset(event->msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
+
+ if (pending)
+ continue;
+ }
+ } while (time_before(jiffies, timeout));
+
+ return ret;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index fc91b6665f905..83da5ba6eeb17 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -328,6 +328,8 @@ enum ice_vsi_state {
struct ice_vsi_stats {
struct ice_ring_stats **tx_ring_stats; /* Tx ring stats array */
struct ice_ring_stats **rx_ring_stats; /* Rx ring stats array */
+ u16 tx_ring_stats_len;
+ u16 rx_ring_stats_len;
};
/* struct that defines a VSI, associated with a dev */
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index b069e6c514fb1..6e7bba4738989 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -95,7 +95,7 @@ ice_eswitch_release_repr(struct ice_pf *pf, struct ice_repr *repr)
return;
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
- metadata_dst_free(repr->dst);
+ dst_release(&repr->dst->dst);
repr->dst = NULL;
ice_fltr_add_mac_and_broadcast(vsi, repr->parent_mac,
ICE_FWD_TO_VSI);
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 8cdc4fda89e97..c71849119d04e 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -338,7 +338,6 @@ static void ice_vsi_free_stats(struct ice_vsi *vsi)
{
struct ice_vsi_stats *vsi_stat;
struct ice_pf *pf = vsi->back;
- int i;
if (vsi->type == ICE_VSI_CHNL)
return;
@@ -349,14 +348,14 @@ static void ice_vsi_free_stats(struct ice_vsi *vsi)
if (!vsi_stat)
return;
- ice_for_each_alloc_txq(vsi, i) {
+ for (int i = 0; i < vsi_stat->tx_ring_stats_len; i++) {
if (vsi_stat->tx_ring_stats[i]) {
kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
}
}
- ice_for_each_alloc_rxq(vsi, i) {
+ for (int i = 0; i < vsi_stat->rx_ring_stats_len; i++) {
if (vsi_stat->rx_ring_stats[i]) {
kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
@@ -513,51 +512,6 @@ static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
return IRQ_HANDLED;
}
-/**
- * ice_vsi_alloc_stat_arrays - Allocate statistics arrays
- * @vsi: VSI pointer
- */
-static int ice_vsi_alloc_stat_arrays(struct ice_vsi *vsi)
-{
- struct ice_vsi_stats *vsi_stat;
- struct ice_pf *pf = vsi->back;
-
- if (vsi->type == ICE_VSI_CHNL)
- return 0;
- if (!pf->vsi_stats)
- return -ENOENT;
-
- if (pf->vsi_stats[vsi->idx])
- /* realloc will happen in rebuild path */
- return 0;
-
- vsi_stat = kzalloc_obj(*vsi_stat);
- if (!vsi_stat)
- return -ENOMEM;
-
- vsi_stat->tx_ring_stats =
- kzalloc_objs(*vsi_stat->tx_ring_stats, vsi->alloc_txq);
- if (!vsi_stat->tx_ring_stats)
- goto err_alloc_tx;
-
- vsi_stat->rx_ring_stats =
- kzalloc_objs(*vsi_stat->rx_ring_stats, vsi->alloc_rxq);
- if (!vsi_stat->rx_ring_stats)
- goto err_alloc_rx;
-
- pf->vsi_stats[vsi->idx] = vsi_stat;
-
- return 0;
-
-err_alloc_rx:
- kfree(vsi_stat->rx_ring_stats);
-err_alloc_tx:
- kfree(vsi_stat->tx_ring_stats);
- kfree(vsi_stat);
- pf->vsi_stats[vsi->idx] = NULL;
- return -ENOMEM;
-}
-
/**
* ice_vsi_alloc_def - set default values for already allocated VSI
* @vsi: ptr to VSI
@@ -2303,6 +2257,85 @@ static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)
return 0;
}
+/**
+ * ice_vsi_realloc_stat_arrays - Frees unused stat structures or alloc new ones
+ * @vsi: VSI pointer
+ * Return: 0 on success or -ENOMEM on allocation failure.
+ */
+static int ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)
+{
+ u16 req_txq = vsi->req_txq ? vsi->req_txq : vsi->alloc_txq;
+ u16 req_rxq = vsi->req_rxq ? vsi->req_rxq : vsi->alloc_rxq;
+ struct ice_ring_stats **tx_ring_stats;
+ struct ice_ring_stats **rx_ring_stats;
+ struct ice_vsi_stats *vsi_stat;
+ struct ice_pf *pf = vsi->back;
+ u16 prev_txq, prev_rxq;
+
+ if (vsi->type == ICE_VSI_CHNL)
+ return 0;
+
+ vsi_stat = pf->vsi_stats[vsi->idx];
+ if (!vsi_stat) {
+ vsi_stat = kzalloc_obj(*vsi_stat);
+ if (!vsi_stat)
+ return -ENOMEM;
+ }
+
+ prev_txq = vsi_stat->tx_ring_stats_len;
+ if (req_txq < prev_txq) {
+ for (int i = req_txq; i < prev_txq; i++) {
+ if (vsi_stat->tx_ring_stats[i]) {
+ kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
+ WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
+ }
+ }
+ }
+
+ tx_ring_stats = vsi_stat->tx_ring_stats;
+ vsi_stat->tx_ring_stats =
+ krealloc_array(vsi_stat->tx_ring_stats, req_txq,
+ sizeof(*vsi_stat->tx_ring_stats),
+ GFP_KERNEL | __GFP_ZERO);
+ if (!vsi_stat->tx_ring_stats) {
+ vsi_stat->tx_ring_stats = tx_ring_stats;
+ goto err_free_partial_vsi_stat;
+ }
+ vsi_stat->tx_ring_stats_len = req_txq;
+
+ prev_rxq = vsi_stat->rx_ring_stats_len;
+ if (req_rxq < prev_rxq) {
+ for (int i = req_rxq; i < prev_rxq; i++) {
+ if (vsi_stat->rx_ring_stats[i]) {
+ kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
+ WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
+ }
+ }
+ }
+
+ rx_ring_stats = vsi_stat->rx_ring_stats;
+ vsi_stat->rx_ring_stats =
+ krealloc_array(vsi_stat->rx_ring_stats, req_rxq,
+ sizeof(*vsi_stat->rx_ring_stats),
+ GFP_KERNEL | __GFP_ZERO);
+ if (!vsi_stat->rx_ring_stats) {
+ vsi_stat->rx_ring_stats = rx_ring_stats;
+ goto err_free_partial_vsi_stat;
+ }
+ vsi_stat->rx_ring_stats_len = req_rxq;
+
+ pf->vsi_stats[vsi->idx] = vsi_stat;
+ return 0;
+
+err_free_partial_vsi_stat:
+ if (!pf->vsi_stats[vsi->idx]) {
+ /* vsi_stat was not visible before current alloc attempt */
+ kfree(vsi_stat->tx_ring_stats);
+ kfree(vsi_stat);
+ }
+ return -ENOMEM;
+}
+
/**
* ice_vsi_cfg_def - configure default VSI based on the type
* @vsi: pointer to VSI
@@ -2320,7 +2353,7 @@ static int ice_vsi_cfg_def(struct ice_vsi *vsi)
return ret;
/* allocate memory for Tx/Rx ring stat pointers */
- ret = ice_vsi_alloc_stat_arrays(vsi);
+ ret = ice_vsi_realloc_stat_arrays(vsi);
if (ret)
goto unroll_vsi_alloc;
@@ -3011,66 +3044,6 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
}
}
-/**
- * ice_vsi_realloc_stat_arrays - Frees unused stat structures or alloc new ones
- * @vsi: VSI pointer
- */
-static int
-ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)
-{
- u16 req_txq = vsi->req_txq ? vsi->req_txq : vsi->alloc_txq;
- u16 req_rxq = vsi->req_rxq ? vsi->req_rxq : vsi->alloc_rxq;
- struct ice_ring_stats **tx_ring_stats;
- struct ice_ring_stats **rx_ring_stats;
- struct ice_vsi_stats *vsi_stat;
- struct ice_pf *pf = vsi->back;
- u16 prev_txq = vsi->alloc_txq;
- u16 prev_rxq = vsi->alloc_rxq;
- int i;
-
- vsi_stat = pf->vsi_stats[vsi->idx];
-
- if (req_txq < prev_txq) {
- for (i = req_txq; i < prev_txq; i++) {
- if (vsi_stat->tx_ring_stats[i]) {
- kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
- WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
- }
- }
- }
-
- tx_ring_stats = vsi_stat->tx_ring_stats;
- vsi_stat->tx_ring_stats =
- krealloc_array(vsi_stat->tx_ring_stats, req_txq,
- sizeof(*vsi_stat->tx_ring_stats),
- GFP_KERNEL | __GFP_ZERO);
- if (!vsi_stat->tx_ring_stats) {
- vsi_stat->tx_ring_stats = tx_ring_stats;
- return -ENOMEM;
- }
-
- if (req_rxq < prev_rxq) {
- for (i = req_rxq; i < prev_rxq; i++) {
- if (vsi_stat->rx_ring_stats[i]) {
- kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
- WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
- }
- }
- }
-
- rx_ring_stats = vsi_stat->rx_ring_stats;
- vsi_stat->rx_ring_stats =
- krealloc_array(vsi_stat->rx_ring_stats, req_rxq,
- sizeof(*vsi_stat->rx_ring_stats),
- GFP_KERNEL | __GFP_ZERO);
- if (!vsi_stat->rx_ring_stats) {
- vsi_stat->rx_ring_stats = rx_ring_stats;
- return -ENOMEM;
- }
-
- return 0;
-}
-
/**
* ice_vsi_rebuild - Rebuild VSI after reset
* @vsi: VSI to be rebuild
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index e04de02155966..5589378998181 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -1366,6 +1366,23 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
return __ice_set_vf_mac(ice_netdev_to_pf(netdev), vf_id, mac);
}
+/**
+ * ice_setup_vf_trust - Enable/disable VF trust mode without reset
+ * @vf: VF to configure
+ * @setting: trust setting
+ *
+ * Update VF flags when changing trust without performing a VF reset.
+ * This is only called when it's safe to skip the reset (VF has no advanced
+ * features configured that need cleanup).
+ */
+static void ice_setup_vf_trust(struct ice_vf *vf, bool setting)
+{
+ if (setting)
+ set_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+ else
+ clear_bit(ICE_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+}
+
/**
* ice_set_vf_trust
* @netdev: network interface device structure
@@ -1401,11 +1418,19 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
mutex_lock(&vf->cfg_lock);
- while (!trusted && vf->num_mac_lldp)
- ice_vf_update_mac_lldp_num(vf, ice_get_vf_vsi(vf), false);
-
- vf->trusted = trusted;
- ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
+ /* Reset only if revoking trust and VF has advanced features configured */
+ if (!trusted &&
+ (vf->num_mac_lldp > 0 ||
+ test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
+ test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))) {
+ while (vf->num_mac_lldp)
+ ice_vf_update_mac_lldp_num(vf, ice_get_vf_vsi(vf), false);
+ vf->trusted = trusted;
+ ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
+ } else {
+ vf->trusted = trusted;
+ ice_setup_vf_trust(vf, trusted);
+ }
dev_info(ice_pf_to_dev(pf), "VF %u is now %strusted\n",
vf_id, trusted ? "" : "un");
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 16fcc8cf61919..39043d8ca1bf4 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -7585,11 +7585,13 @@ static int __igc_resume(struct device *dev, bool rpm)
err = __igc_open(netdev, true);
if (!rpm)
rtnl_unlock();
- if (!err)
- netif_device_attach(netdev);
+ if (err)
+ return err;
}
- return err;
+ netif_device_attach(netdev);
+
+ return 0;
}
static int igc_resume(struct device *dev)
|
| 3/2 | 2026/08/04 23:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12548 output: 42 thoughts: 1301 Thoughts: **Analyzing the Reachability of Intel Ethernet Driver Patches** Okay, so I'm looking at this patch series that tweaks a bunch of Intel ethernet drivers: `i40e`, `iavf`, `ice`, and `igc`. It's all functional stuff – fixing memory comparisons, memory leaks, and optimizing some VF trust configurations. The question that immediately pops into my head is, how easy is this to test? Are these drivers even reachable in a typical virtualized environment? Let's break this down. `i40e`, `iavf`, `ice`, and `igc` are all *physical* hardware drivers. They're meant to work with actual Intel Ethernet hardware. I know QEMU emulates some Intel NICs – `e1000`, `e1000e`, and `igb` spring to mind. But does QEMU emulate the specific devices targeted by this patch series? I can't instantly search QEMU source right now, but a quick check reveals that no, QEMU doesn't emulate `i40e`, `ice`, or `igc` out of the box. Okay, so that’s a big "no". I'm pretty sure `iavf` is also not emulated, since it's a VF driver, which complicates things further. It is interesting to look if QEMU emulates `igc`, but probably not. Wait, are these drivers the kind of "vendor-specific PCIe switch, SmartNIC, or GPU drivers" that require actual PCIe hardware? Yes, they are! They're standard NIC drivers, but they require the physical card to work. So, even if QEMU doesn't directly emulate them, could we fuzz them somehow? Syzkaller has some PCI device injection capabilities, but it usually relies on emulated devices. Maybe `sys/linux/socket_netlink_generic_devlink.txt` is useful. However, if the PCI device isn't present, the driver's `probe` function won't even be called. The patch would be unreachable. Alright, what about virtual or emulated ways to reach these code paths? `iavf` is an Adaptive Virtual Function driver, so that could be promising, but still tricky. I'd need to confirm with the syzkaller setup if they are reachable, which I cannot with the tools that I have. I cannot search `sys/linux` for the drivers using the current prompt's functions. These are standard PCI drivers. Given that QEMU doesn't emulate them and they're meant for physical hardware, it seems unlikely that I can reach these driver changes within a standard virtualized environment like QEMU or GCE. I need a real machine. |
| 4/2 | 2026/08/04 23:17 | tool | grepper |
0mArgs:{
"Expression": "MODULE_DEVICE_TABLE\\(pci",
"PathPrefix": "drivers/net/ethernet/intel/i40e/"
}Results: {
"Output": "drivers/net/ethernet/intel/i40e/i40e_main.c=65=static const struct pci_device_id i40e_pci_tbl[] = {\n--\ndrivers/net/ethernet/intel/i40e/i40e_main.c-103-};\ndrivers/net/ethernet/intel/i40e/i40e_main.c:104:MODULE_DEVICE_TABLE(pci, i40e_pci_tbl);\ndrivers/net/ethernet/intel/i40e/i40e_main.c-105-\n"
} |
| 5/2 | 2026/08/04 23:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14643 output: 122 thoughts: 807 Thoughts: **PCI Driver Fuzzing Analysis** Okay, so we're talking about PCI drivers here. Specifically, I'm thinking about those Intel Ethernet drivers – `i40e`, `ice`, `iavf`, and `igc`. The problem is, QEMU doesn't emulate any of them. That immediately throws a wrench in the fuzzing process, right? My initial thought was, "Can syzkaller's `syz_pci_setup` or something similar simulate PCI config space enough to get these drivers probed?" Then I remembered that syzkaller *does* have PCI fuzzing support! It uses `syz_pci_setup`, or the `vhci`, or similar virtual mechanisms. But hold on, the documentation specifies that syzkaller's PCI fuzzing relies on a virtual PCI host bridge, which then injects PCI devices. Okay, let me check the "reachable" criteria in the prompt. Ah, here it is: the prompt explicitly says to return `WorthFuzzing=false` for "Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers... that require physical PCIe hardware cards not emulated in standard QEMU." So, are these Intel Ethernet drivers "vendor-specific"? Well, `i40e` is 40 Gigabit, `ice` is 100 Gigabit (E800 series), and `igc` is 2.5 Gigabit. They're all physical PCIe hardware cards. And I *know* QEMU doesn't emulate these NICs. Now, would syzkaller even be able to get them going? Maybe, but it would be really tough. It's unlikely that syzkaller could get past their initialization routines since they require firmware, read specific hardware registers, or require valid MAC addresses from EEPROM, which would all be absent in the virtualized environment. For instance, `i40e` demands firmware (AdminQ). A basic PCI fuzzer is just going to fail at the `i40e_probe` stage because it's expecting to communicate with the firmware. Same with `ice` and `iavf`. Let me just double-check, but QEMU doesn't emulate `igc`, it has added `igb` (Intel 82576). Not `igc` (Intel I225). And it also doesn't emulate `i40e` or `ice`. It does emulate other NICs, like `e1000`, `e1000e`, `igb`, etc. The bottom line is that the code changes are in physical PCIe hardware drivers that are *not* emulated in standard QEMU. That means the code paths are unreachable without specific hardware emulation. Therefore, I will return `WorthFuzzing=false`. My reasoning is simple: these are physical PCIe NIC drivers (`i40e`, `iavf`, `ice`, `igc`) that need hardware not found in standard QEMU, making them unreachable in any virtualized fuzzing. |
| 6/2 | 2026/08/04 23:17 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies Intel Ethernet drivers (i40e, iavf, ice, igc). These are drivers for physical PCIe hardware cards that are not emulated in standard QEMU. Furthermore, these drivers typically require complex interactions with hardware firmware (e.g., AdminQ) during probe, meaning they cannot be successfully initialized or reached via generic PCI fuzzing in virtualized environments. Therefore, the modified code paths are unreachable during fuzzing.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies Intel Ethernet drivers (i40e, iavf, ice, igc). These are drivers for physical PCIe hardware cards that are not emulated in standard QEMU. Furthermore, these drivers typically require complex interactions with hardware firmware (e.g., AdminQ) during probe, meaning they cannot be successfully initialized or reached via generic PCI fuzzing in virtualized environments. Therefore, the modified code paths are unreachable during fuzzing.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|