⬢ DragonFlyBSD Kernel Audit
DF-4306 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/ig_hal/e1000_80003es2lan.c
+++ b/sys/dev/netif/ig_hal/e1000_80003es2lan.c
@@ -449,11 +449,20 @@
 static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
 {
 	u32 swfw_sync;
+	s32 i = 0;
 
 	DEBUGFUNC("e1000_release_swfw_sync_80003es2lan");
 
-	while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
-		; /* Empty */
+	/* Bounded retry: a wedged SMBI bit (stuck firmware hold or dead
+	 * device) must not spin this CPU forever while the caller holds
+	 * the driver serializer.  Mirrors the acquire-side bound.  */
+	while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) {
+		if (++i >= 50) {
+			DEBUGOUT("SW_FW_SYNC release: HW semaphore stuck, "
+				 "giving up (PHY/NVM lock left held)\n");
+			return;
+		}
+	}
 
 	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
 	swfw_sync &= ~mask;