Author: kevans
Date: Thu Jan 24 03:47:47 2019
New Revision: 343384
URL: https://svnweb.freebsd.org/changeset/base/343384

Log:
  iwm - Clear Time Event active state, when receiving End Notification.
  
  * This hopefully avoids some firmware panics, I was occasionally seeing,
  when iwm disconnects upon losing signal to an access point at some point.
  
  * This is synchronizing the if_iwm_time_event.c file a bit more from the
  corresponding Linux iwlwifi/mvm/time-event.c.
  
  Taken-From:     Linux iwlwifi
  
  Submitted by: Augustin Cavalier <waddlespl...@gmail.com> (Haiku)
  Obtained from:        DragonFlyBSD (e8cb71584a6a72232c13151d60e57f7f229220eb)

Modified:
  head/sys/dev/iwm/if_iwm.c
  head/sys/dev/iwm/if_iwm_time_event.c
  head/sys/dev/iwm/if_iwm_time_event.h
  head/sys/dev/iwm/if_iwmvar.h

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c   Thu Jan 24 03:47:04 2019        (r343383)
+++ head/sys/dev/iwm/if_iwm.c   Thu Jan 24 03:47:47 2019        (r343384)
@@ -5375,15 +5375,9 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m)
                        break;
                }
 
-               case IWM_TIME_EVENT_NOTIFICATION: {
-                       struct iwm_time_event_notif *notif;
-                       notif = (void *)pkt->data;
-
-                       IWM_DPRINTF(sc, IWM_DEBUG_INTR,
-                           "TE notif status = 0x%x action = 0x%x\n",
-                           notif->status, notif->action);
+               case IWM_TIME_EVENT_NOTIFICATION:
+                       iwm_mvm_rx_time_event_notif(sc, pkt);
                        break;
-               }
 
                /*
                 * Firmware versions 21 and 22 generate some DEBUG_LOG_MSG

Modified: head/sys/dev/iwm/if_iwm_time_event.c
==============================================================================
--- head/sys/dev/iwm/if_iwm_time_event.c        Thu Jan 24 03:47:04 2019        
(r343383)
+++ head/sys/dev/iwm/if_iwm_time_event.c        Thu Jan 24 03:47:47 2019        
(r343384)
@@ -159,13 +159,74 @@ __FBSDID("$FreeBSD$");
 #include <dev/iwm/if_iwm_pcie_trans.h>
 #include <dev/iwm/if_iwm_time_event.h>
 
+#define TU_TO_HZ(tu)   (((uint64_t)(tu) * 1024 * hz) / 1000000)
+
+static void
+iwm_mvm_te_clear_data(struct iwm_softc *sc)
+{
+       sc->sc_time_event_uid = 0;
+       sc->sc_time_event_duration = 0;
+       sc->sc_time_event_end_ticks = 0;
+       sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;
+}
+
 /*
- * For the high priority TE use a time event type that has similar priority to
- * the FW's action scan priority.
+ * Handles a FW notification for an event that is known to the driver.
+ *
+ * @mvm: the mvm component
+ * @te_data: the time event data
+ * @notif: the notification data corresponding the time event data.
  */
-#define IWM_MVM_ROC_TE_TYPE_NORMAL IWM_TE_P2P_DEVICE_DISCOVERABLE
-#define IWM_MVM_ROC_TE_TYPE_MGMT_TX IWM_TE_P2P_CLIENT_ASSOC
+static void
+iwm_mvm_te_handle_notif(struct iwm_softc *sc,
+    struct iwm_time_event_notif *notif)
+{
+       IWM_DPRINTF(sc, IWM_DEBUG_TE,
+           "Handle time event notif - UID = 0x%x action %d\n",
+           le32toh(notif->unique_id),
+           le32toh(notif->action));
 
+       if (!le32toh(notif->status)) {
+               const char *msg;
+
+               if (notif->action & htole32(IWM_TE_V2_NOTIF_HOST_EVENT_START))
+                       msg = "Time Event start notification failure";
+               else
+                       msg = "Time Event end notification failure";
+
+               IWM_DPRINTF(sc, IWM_DEBUG_TE, "%s\n", msg);
+       }
+
+       if (le32toh(notif->action) & IWM_TE_V2_NOTIF_HOST_EVENT_END) {
+               IWM_DPRINTF(sc, IWM_DEBUG_TE,
+                   "TE ended - current time %d, estimated end %d\n",
+                   ticks, sc->sc_time_event_end_ticks);
+
+               iwm_mvm_te_clear_data(sc);
+       } else if (le32toh(notif->action) & IWM_TE_V2_NOTIF_HOST_EVENT_START) {
+               sc->sc_time_event_end_ticks =
+                   ticks + TU_TO_HZ(sc->sc_time_event_duration);
+       } else {
+               device_printf(sc->sc_dev, "Got TE with unknown action\n");
+       }
+}
+
+/*
+ * The Rx handler for time event notifications
+ */
+void
+iwm_mvm_rx_time_event_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
+{
+       struct iwm_time_event_notif *notif = (void *)pkt->data;
+
+       IWM_DPRINTF(sc, IWM_DEBUG_TE,
+           "Time event notification - UID = 0x%x action %d\n",
+           le32toh(notif->unique_id),
+           le32toh(notif->action));
+
+       iwm_mvm_te_handle_notif(sc, notif);
+}
+
 static int
 iwm_mvm_te_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
     void *data)
@@ -241,6 +302,8 @@ iwm_mvm_time_event_send_add(struct iwm_softc *sc, stru
        IWM_DPRINTF(sc, IWM_DEBUG_TE,
            "Add new TE, duration %d TU\n", le32toh(te_cmd->duration));
 
+       sc->sc_time_event_duration = le32toh(te_cmd->duration);
+
        /*
         * Use a notification wait, which really just processes the
         * command response and doesn't wait for anything, in order
@@ -279,8 +342,6 @@ iwm_mvm_time_event_send_add(struct iwm_softc *sc, stru
        return ret;
 }
 
-#define TU_TO_HZ(tu)   (((uint64_t)(tu) * 1024 * hz) / 1000000)
-
 void
 iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_vap *ivp,
        uint32_t duration, uint32_t max_delay, boolean_t wait_for_notif)
@@ -362,7 +423,7 @@ iwm_mvm_stop_session_protection(struct iwm_softc *sc, 
            "%s: Removing TE 0x%x\n", __func__, le32toh(time_cmd.id));
        if (iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, 0, sizeof(time_cmd),
            &time_cmd) == 0)
-               sc->sc_flags &= ~IWM_FLAG_TE_ACTIVE;
+               iwm_mvm_te_clear_data(sc);
 
        DELAY(100);
 }

Modified: head/sys/dev/iwm/if_iwm_time_event.h
==============================================================================
--- head/sys/dev/iwm/if_iwm_time_event.h        Thu Jan 24 03:47:04 2019        
(r343383)
+++ head/sys/dev/iwm/if_iwm_time_event.h        Thu Jan 24 03:47:47 2019        
(r343384)
@@ -107,6 +107,8 @@
 #ifndef        __IF_IWM_TIME_EVENT_H__
 #define        __IF_IWM_TIME_EVENT_H__
 
+extern void iwm_mvm_rx_time_event_notif(struct iwm_softc *sc,
+           struct iwm_rx_packet *pkt);
 extern void iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_vap *ivp,
            uint32_t duration, uint32_t max_delay, boolean_t wait_for_notif);
 extern void iwm_mvm_stop_session_protection(struct iwm_softc *sc,

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h        Thu Jan 24 03:47:04 2019        
(r343383)
+++ head/sys/dev/iwm/if_iwmvar.h        Thu Jan 24 03:47:47 2019        
(r343384)
@@ -566,6 +566,12 @@ struct iwm_softc {
 
        /* Unique ID (assigned by the firmware) of the current Time Event. */
        uint32_t                sc_time_event_uid;
+
+       /* Duration of the Time Event in TU. */
+       uint32_t                sc_time_event_duration;
+
+       /* Expected end of the Time Event in HZ ticks. */
+       int                     sc_time_event_end_ticks;
 };
 
 #define IWM_LOCK_INIT(_sc) \
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to