Some em chips have a semaphore ("software flag") to synchronize access
to certain registers between OS and firmware (ME/AMT).

Make the logic to get the flag match the logic in freebsd. This includes
higher timeouts and waiting for a previous unlock to complete before
trying a lock again.
---
 sys/dev/pci/if_em_hw.c | 22 +++++++++++++++++++---
 sys/dev/pci/if_em_hw.h |  2 ++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git sys/dev/pci/if_em_hw.c sys/dev/pci/if_em_hw.c
index e5084252c29..5bba83cbcd4 100644
--- sys/dev/pci/if_em_hw.c
+++ sys/dev/pci/if_em_hw.c
@@ -9613,9 +9613,21 @@ em_get_software_flag(struct em_hw *hw)
        if (IS_ICH8(hw->mac_type)) {
                while (timeout) {
                        extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
-                       extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
-                       E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+                       if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG))
+                               break;
+                       msec_delay_irq(1);
+                       timeout--;
+               }
+               if (!timeout) {
+                       printf("%s: SW has already locked the resource?\n",
+                           __func__);
+                       return -E1000_ERR_CONFIG;
+               }
+               timeout = SW_FLAG_TIMEOUT;
+               extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
+               E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
 
+               while (timeout) {
                        extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
                        if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
                                break;
@@ -9624,7 +9636,11 @@ em_get_software_flag(struct em_hw *hw)
                }
 
                if (!timeout) {
-                       DEBUGOUT("FW or HW locks the resource too long.\n");
+                       printf("Failed to acquire the semaphore, FW or HW "
+                           "has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n",
+                           E1000_READ_REG(hw, FWSM), extcnf_ctrl);
+                       extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+                       E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
                        return -E1000_ERR_CONFIG;
                }
        }
diff --git sys/dev/pci/if_em_hw.h sys/dev/pci/if_em_hw.h
index 5e415e60a34..71dc91e5582 100644
--- sys/dev/pci/if_em_hw.h
+++ sys/dev/pci/if_em_hw.h
@@ -2755,6 +2755,8 @@ struct em_host_command_info {
 #define AUTO_READ_DONE_TIMEOUT      10
 /* Number of milliseconds we wait for PHY configuration done after MAC reset */
 #define PHY_CFG_TIMEOUT             100
+/* SW Semaphore flag timeout in ms */
+#define SW_FLAG_TIMEOUT                1000
 
 #define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
 
-- 
2.13.0

Reply via email to