summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2021-07-07 08:05:12 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2021-07-07 08:05:12 +0000
commit44d8d4928d73a453d74a52438889e9531342f21a (patch)
tree93e064a55ae14e0e37e19cb0c406b3fc350c4f78
parent4c18c1450aeccd1a1579a34304ef364cf62c9bf9 (diff)
Support a new time quota command required for newer iwm(4) firmware.
-rw-r--r--sys/dev/pci/if_iwm.c94
-rw-r--r--sys/dev/pci/if_iwmreg.h39
2 files changed, 117 insertions, 16 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index a3bf3f8ac47..59bdeb8dfe1 100644
--- a/sys/dev/pci/if_iwm.c
+++ b/sys/dev/pci/if_iwm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwm.c,v 1.333 2021/06/30 09:45:47 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.334 2021/07/07 08:05:11 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -462,6 +462,7 @@ void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
void iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,
struct iwm_mac_data_sta *, int);
int iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t, int);
+int iwm_update_quotas_v1(struct iwm_softc *, struct iwm_node *, int);
int iwm_update_quotas(struct iwm_softc *, struct iwm_node *, int);
void iwm_add_task(struct iwm_softc *, struct taskq *, struct task *);
void iwm_del_task(struct iwm_softc *, struct taskq *, struct task *);
@@ -7762,6 +7763,67 @@ iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action,
}
int
+iwm_update_quotas_v1(struct iwm_softc *sc, struct iwm_node *in, int running)
+{
+ struct iwm_time_quota_cmd_v1 cmd;
+ int i, idx, num_active_macs, quota, quota_rem;
+ int colors[IWM_MAX_BINDINGS] = { -1, -1, -1, -1, };
+ int n_ifs[IWM_MAX_BINDINGS] = {0, };
+ uint16_t id;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ /* currently, PHY ID == binding ID */
+ if (in && in->in_phyctxt) {
+ id = in->in_phyctxt->id;
+ KASSERT(id < IWM_MAX_BINDINGS);
+ colors[id] = in->in_phyctxt->color;
+ if (running)
+ n_ifs[id] = 1;
+ }
+
+ /*
+ * The FW's scheduling session consists of
+ * IWM_MAX_QUOTA fragments. Divide these fragments
+ * equally between all the bindings that require quota
+ */
+ num_active_macs = 0;
+ for (i = 0; i < IWM_MAX_BINDINGS; i++) {
+ cmd.quotas[i].id_and_color = htole32(IWM_FW_CTXT_INVALID);
+ num_active_macs += n_ifs[i];
+ }
+
+ quota = 0;
+ quota_rem = 0;
+ if (num_active_macs) {
+ quota = IWM_MAX_QUOTA / num_active_macs;
+ quota_rem = IWM_MAX_QUOTA % num_active_macs;
+ }
+
+ for (idx = 0, i = 0; i < IWM_MAX_BINDINGS; i++) {
+ if (colors[i] < 0)
+ continue;
+
+ cmd.quotas[idx].id_and_color =
+ htole32(IWM_FW_CMD_ID_AND_COLOR(i, colors[i]));
+
+ if (n_ifs[i] <= 0) {
+ cmd.quotas[idx].quota = htole32(0);
+ cmd.quotas[idx].max_duration = htole32(0);
+ } else {
+ cmd.quotas[idx].quota = htole32(quota * n_ifs[i]);
+ cmd.quotas[idx].max_duration = htole32(0);
+ }
+ idx++;
+ }
+
+ /* Give the remainder of the session to the first binding */
+ cmd.quotas[0].quota = htole32(le32toh(cmd.quotas[0].quota) + quota_rem);
+
+ return iwm_send_cmd_pdu(sc, IWM_TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);
+}
+
+int
iwm_update_quotas(struct iwm_softc *sc, struct iwm_node *in, int running)
{
struct iwm_time_quota_cmd cmd;
@@ -7770,6 +7832,9 @@ iwm_update_quotas(struct iwm_softc *sc, struct iwm_node *in, int running)
int n_ifs[IWM_MAX_BINDINGS] = {0, };
uint16_t id;
+ if (!isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_QUOTA_LOW_LATENCY))
+ return iwm_update_quotas_v1(sc, in, running);
+
memset(&cmd, 0, sizeof(cmd));
/* currently, PHY ID == binding ID */
@@ -7819,8 +7884,7 @@ iwm_update_quotas(struct iwm_softc *sc, struct iwm_node *in, int running)
/* Give the remainder of the session to the first binding */
cmd.quotas[0].quota = htole32(le32toh(cmd.quotas[0].quota) + quota_rem);
- return iwm_send_cmd_pdu(sc, IWM_TIME_QUOTA_CMD, 0,
- sizeof(cmd), &cmd);
+ return iwm_send_cmd_pdu(sc, IWM_TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);
}
void
@@ -8235,11 +8299,13 @@ iwm_run(struct iwm_softc *sc)
return err;
}
- err = iwm_update_quotas(sc, in, 1);
- if (err) {
- printf("%s: could not update quotas (error %d)\n",
- DEVNAME(sc), err);
- return err;
+ if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {
+ err = iwm_update_quotas(sc, in, 1);
+ if (err) {
+ printf("%s: could not update quotas (error %d)\n",
+ DEVNAME(sc), err);
+ return err;
+ }
}
ieee80211_amrr_node_init(&sc->sc_amrr, &in->in_amn);
@@ -8279,11 +8345,13 @@ iwm_run_stop(struct iwm_softc *sc)
iwm_disable_beacon_filter(sc);
- err = iwm_update_quotas(sc, in, 0);
- if (err) {
- printf("%s: could not update quotas (error %d)\n",
- DEVNAME(sc), err);
- return err;
+ if (!isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA)) {
+ err = iwm_update_quotas(sc, in, 0);
+ if (err) {
+ printf("%s: could not update quotas (error %d)\n",
+ DEVNAME(sc), err);
+ return err;
+ }
}
err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 0);
diff --git a/sys/dev/pci/if_iwmreg.h b/sys/dev/pci/if_iwmreg.h
index a5062160551..f93355f9a61 100644
--- a/sys/dev/pci/if_iwmreg.h
+++ b/sys/dev/pci/if_iwmreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwmreg.h,v 1.53 2021/06/30 09:45:47 stsp Exp $ */
+/* $OpenBSD: if_iwmreg.h,v 1.54 2021/07/07 08:05:11 stsp Exp $ */
/******************************************************************************
*
@@ -825,6 +825,7 @@ enum msix_ivar_for_cause {
#define IWM_UCODE_TLV_API_NAN2_VER2 31
#define IWM_UCODE_TLV_API_ADAPTIVE_DWELL 32
#define IWM_UCODE_TLV_API_NEW_RX_STATS 35
+#define IWM_UCODE_TLV_API_QUOTA_LOW_LATENCY 38
#define IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2 42
#define IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER 58
#define IWM_NUM_UCODE_TLV_API 128
@@ -915,6 +916,7 @@ enum msix_ivar_for_cause {
#define IWM_UCODE_TLV_CAPA_GSCAN_SUPPORT 31
#define IWM_UCODE_TLV_CAPA_NAN_SUPPORT 34
#define IWM_UCODE_TLV_CAPA_UMAC_UPLOAD 35
+#define IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA 44
#define IWM_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE 64
#define IWM_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS 65
#define IWM_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT 67
@@ -2867,7 +2869,7 @@ struct iwm_binding_cmd {
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
*/
-struct iwm_time_quota_data {
+struct iwm_time_quota_data_v1 {
uint32_t id_and_color;
uint32_t quota;
uint32_t max_duration;
@@ -2878,9 +2880,40 @@ struct iwm_time_quota_data {
* ( IWM_TIME_QUOTA_CMD = 0x2c )
* @quotas: allocations per binding
*/
+struct iwm_time_quota_cmd_v1 {
+ struct iwm_time_quota_data_v1 quotas[IWM_MAX_BINDINGS];
+} __packed; /* IWM_TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */
+
+#define IWM_QUOTA_LOW_LATENCY_NONE 0
+#define IWM_QUOTA_LOW_LATENCY_TX (1 << 0)
+#define IWM_QUOTA_LOW_LATENCY_RX (1 << 1)
+
+/**
+ * struct iwm_time_quota_data - configuration of time quota per binding
+ * @id_and_color: ID and color of the relevant Binding.
+ * @quota: absolute time quota in TU. The scheduler will try to divide the
+ * remainig quota (after Time Events) according to this quota.
+ * @max_duration: max uninterrupted context duration in TU
+ * @low_latency: low latency status IWM_QUOTA_LOW_LATENCY_*
+ */
+struct iwm_time_quota_data {
+ uint32_t id_and_color;
+ uint32_t quota;
+ uint32_t max_duration;
+ uint32_t low_latency;
+}; /* TIME_QUOTA_DATA_API_S_VER_2 */
+
+/**
+ * struct iwm_time_quota_cmd - configuration of time quota between bindings
+ * ( TIME_QUOTA_CMD = 0x2c )
+ * Note: on non-CDB the fourth one is the auxilary mac and is essentially zero.
+ * On CDB the fourth one is a regular binding.
+ *
+ * @quotas: allocations per binding
+ */
struct iwm_time_quota_cmd {
struct iwm_time_quota_data quotas[IWM_MAX_BINDINGS];
-} __packed; /* IWM_TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */
+}; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_2 */
/* PHY context */