svn commit: r343384 - head/sys/dev/iwm
Kyle Evans
kevans at FreeBSD.org
Thu Jan 24 03:47:48 UTC 2019
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 <waddlesplash at 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) \
More information about the svn-src-all
mailing list