aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpica/acpi_apei.c2
-rw-r--r--sys/dev/acpica/acpi_powerres.c110
-rw-r--r--sys/dev/ath/if_ath_tx.c14
-rw-r--r--sys/dev/iwx/if_iwx.c187
-rw-r--r--sys/dev/iwx/if_iwxreg.h4
-rw-r--r--sys/dev/pci/pci.c10
-rw-r--r--sys/dev/vmware/vmxnet3/if_vmx.c7
-rw-r--r--sys/dev/watchdog/watchdog.c2
8 files changed, 146 insertions, 190 deletions
diff --git a/sys/dev/acpica/acpi_apei.c b/sys/dev/acpica/acpi_apei.c
index 9cfd46c97430..624c81ad1b4f 100644
--- a/sys/dev/acpica/acpi_apei.c
+++ b/sys/dev/acpica/acpi_apei.c
@@ -754,7 +754,7 @@ apei_detach(device_t dev)
apei_nmi = NULL;
apei_nmi_nges = NULL;
if (sc->nges.swi_ih != NULL) {
- swi_remove(&sc->nges.swi_ih);
+ swi_remove(sc->nges.swi_ih);
sc->nges.swi_ih = NULL;
}
if (acpi_get_handle(dev) != NULL) {
diff --git a/sys/dev/acpica/acpi_powerres.c b/sys/dev/acpica/acpi_powerres.c
index 0baa5c595470..29d1690f1bdd 100644
--- a/sys/dev/acpica/acpi_powerres.c
+++ b/sys/dev/acpica/acpi_powerres.c
@@ -76,13 +76,6 @@ struct acpi_powerconsumer {
/* Device which is powered */
ACPI_HANDLE ac_consumer;
int ac_state;
-
- struct {
- bool prx_has;
- size_t prx_count;
- ACPI_HANDLE *prx_deps;
- } ac_prx[ACPI_D_STATE_COUNT];
-
TAILQ_ENTRY(acpi_powerconsumer) ac_link;
TAILQ_HEAD(,acpi_powerreference) ac_references;
};
@@ -103,7 +96,9 @@ static TAILQ_HEAD(acpi_powerconsumer_list, acpi_powerconsumer)
ACPI_SERIAL_DECL(powerres, "ACPI power resources");
static ACPI_STATUS acpi_pwr_register_consumer(ACPI_HANDLE consumer);
+#ifdef notyet
static ACPI_STATUS acpi_pwr_deregister_consumer(ACPI_HANDLE consumer);
+#endif /* notyet */
static ACPI_STATUS acpi_pwr_register_resource(ACPI_HANDLE res);
#ifdef notyet
static ACPI_STATUS acpi_pwr_deregister_resource(ACPI_HANDLE res);
@@ -227,84 +222,6 @@ acpi_pwr_deregister_resource(ACPI_HANDLE res)
#endif /* notyet */
/*
- * Evaluate the _PRx (power resources each D-state depends on). This also
- * populates the acpi_powerresources queue with the power resources discovered
- * during this step.
- *
- * ACPI 7.3.8 - 7.3.11 guarantee that _PRx will return the same data each
- * time they are evaluated.
- *
- * If this function fails, acpi_pwr_deregister_consumer() must be called on the
- * power consumer to free already allocated memory.
- */
-static ACPI_STATUS
-acpi_pwr_get_power_resources(ACPI_HANDLE consumer, struct acpi_powerconsumer *pc)
-{
- ACPI_INTEGER status;
- ACPI_STRING reslist_name;
- ACPI_HANDLE reslist_handle;
- ACPI_STRING reslist_names[] = {"_PR0", "_PR1", "_PR2", "_PR3"};
- ACPI_BUFFER reslist;
- ACPI_OBJECT *reslist_object;
- ACPI_OBJECT *dep;
- ACPI_HANDLE *res;
-
- ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
- ACPI_SERIAL_ASSERT(powerres);
-
- MPASS(consumer != NULL);
-
- for (int state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) {
- pc->ac_prx[state].prx_has = false;
- pc->ac_prx[state].prx_count = 0;
- pc->ac_prx[state].prx_deps = NULL;
-
- reslist_name = reslist_names[state - ACPI_STATE_D0];
- if (ACPI_FAILURE(AcpiGetHandle(consumer, reslist_name, &reslist_handle)))
- continue;
-
- reslist.Pointer = NULL;
- reslist.Length = ACPI_ALLOCATE_BUFFER;
- status = AcpiEvaluateObjectTyped(reslist_handle, NULL, NULL, &reslist,
- ACPI_TYPE_PACKAGE);
- if (ACPI_FAILURE(status) || reslist.Pointer == NULL)
- /*
- * ACPI_ALLOCATE_BUFFER entails everything will be freed on error
- * by AcpiEvaluateObjectTyped.
- */
- continue;
-
- reslist_object = (ACPI_OBJECT *)reslist.Pointer;
- pc->ac_prx[state].prx_has = true;
- pc->ac_prx[state].prx_count = reslist_object->Package.Count;
-
- if (reslist_object->Package.Count == 0) {
- AcpiOsFree(reslist_object);
- continue;
- }
-
- pc->ac_prx[state].prx_deps = mallocarray(pc->ac_prx[state].prx_count,
- sizeof(*pc->ac_prx[state].prx_deps), M_ACPIPWR, M_NOWAIT);
- if (pc->ac_prx[state].prx_deps == NULL) {
- AcpiOsFree(reslist_object);
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
- for (size_t i = 0; i < reslist_object->Package.Count; i++) {
- dep = &reslist_object->Package.Elements[i];
- res = dep->Reference.Handle;
- pc->ac_prx[state].prx_deps[i] = res;
-
- /* It's fine to attempt to register the same resource twice. */
- acpi_pwr_register_resource(res);
- }
- AcpiOsFree(reslist_object);
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-/*
* Register a power consumer.
*
* It's OK to call this if we already know about the consumer.
@@ -312,7 +229,6 @@ acpi_pwr_get_power_resources(ACPI_HANDLE consumer, struct acpi_powerconsumer *pc
static ACPI_STATUS
acpi_pwr_register_consumer(ACPI_HANDLE consumer)
{
- ACPI_INTEGER status;
struct acpi_powerconsumer *pc;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -323,27 +239,12 @@ acpi_pwr_register_consumer(ACPI_HANDLE consumer)
return_ACPI_STATUS (AE_OK);
/* Allocate a new power consumer */
- if ((pc = malloc(sizeof(*pc), M_ACPIPWR, M_NOWAIT | M_ZERO)) == NULL)
+ if ((pc = malloc(sizeof(*pc), M_ACPIPWR, M_NOWAIT)) == NULL)
return_ACPI_STATUS (AE_NO_MEMORY);
TAILQ_INSERT_HEAD(&acpi_powerconsumers, pc, ac_link);
TAILQ_INIT(&pc->ac_references);
pc->ac_consumer = consumer;
- /*
- * Get all its power resource dependencies, if it has _PRx. We do this now
- * as an opportunity to populate the acpi_powerresources queue.
- *
- * If this fails, immediately deregister it.
- */
- status = acpi_pwr_get_power_resources(consumer, pc);
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
- "failed to get power resources for %s\n",
- acpi_name(consumer)));
- acpi_pwr_deregister_consumer(consumer);
- return_ACPI_STATUS (status);
- }
-
/* XXX we should try to find its current state */
pc->ac_state = ACPI_STATE_UNKNOWN;
@@ -353,6 +254,7 @@ acpi_pwr_register_consumer(ACPI_HANDLE consumer)
return_ACPI_STATUS (AE_OK);
}
+#ifdef notyet
/*
* Deregister a power consumer.
*
@@ -377,9 +279,6 @@ acpi_pwr_deregister_consumer(ACPI_HANDLE consumer)
/* Pull the consumer off the list and free it */
TAILQ_REMOVE(&acpi_powerconsumers, pc, ac_link);
- for (size_t i = 0; i < sizeof(pc->ac_prx) / sizeof(*pc->ac_prx); i++)
- if (pc->ac_prx[i].prx_deps != NULL)
- free(pc->ac_prx[i].prx_deps, M_ACPIPWR);
free(pc, M_ACPIPWR);
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "deregistered power consumer %s\n",
@@ -387,6 +286,7 @@ acpi_pwr_deregister_consumer(ACPI_HANDLE consumer)
return_ACPI_STATUS (AE_OK);
}
+#endif /* notyet */
/*
* Set a power consumer to a particular power state.
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index deadd63c3d18..9ac591c14943 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -971,6 +971,12 @@ ath_legacy_xmit_handoff(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_handoff_hw(sc, txq, bf);
}
+/*
+ * Setup a frame for encryption.
+ *
+ * If this fails, then an non-zero error is returned. The mbuf
+ * must be freed by the caller.
+ */
static int
ath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen,
@@ -1547,6 +1553,10 @@ ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq,
*
* Note that this may cause the mbuf to be reallocated, so
* m0 may not be valid.
+ *
+ * If there's a problem then the mbuf is freed and an error
+ * is returned. The ath_buf then needs to be freed by the
+ * caller.
*/
static int
ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
@@ -2073,9 +2083,8 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
/* This also sets up the DMA map; crypto; frame parameters, etc */
r = ath_tx_normal_setup(sc, ni, bf, m0, txq);
-
if (r != 0)
- goto done;
+ return (r);
/* At this point m0 could have changed! */
m0 = bf->bf_m;
@@ -2132,7 +2141,6 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
ath_tx_leak_count_update(sc, tid, bf);
ath_tx_xmit_normal(sc, txq, bf);
#endif
-done:
return 0;
}
diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c
index 8422fcb787c3..04ed09f04604 100644
--- a/sys/dev/iwx/if_iwx.c
+++ b/sys/dev/iwx/if_iwx.c
@@ -4805,6 +4805,8 @@ iwx_rx_tx_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
static void
iwx_clear_oactive(struct iwx_softc *sc, struct iwx_tx_ring *ring)
{
+ IWX_ASSERT_LOCKED(sc);
+
if (ring->queued < iwx_lomark) {
sc->qfullmsk &= ~(1 << ring->qid);
if (sc->qfullmsk == 0 /* && ifq_is_oactive(&ifp->if_snd) */) {
@@ -4890,11 +4892,19 @@ iwx_rx_bmiss(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
bus_dmamap_sync(sc->rxq.data_dmat, data->map,
BUS_DMASYNC_POSTREAD);
+ IWX_DPRINTF(sc, IWX_DEBUG_BEACON,
+ "%s: mac_id=%u, cmslrx=%u, cmb=%u, neb=%d, nrb=%u\n",
+ __func__,
+ le32toh(mbn->mac_id),
+ le32toh(mbn->consec_missed_beacons_since_last_rx),
+ le32toh(mbn->consec_missed_beacons),
+ le32toh(mbn->num_expected_beacons),
+ le32toh(mbn->num_recvd_beacons));
+
missed = le32toh(mbn->consec_missed_beacons_since_last_rx);
if (missed > vap->iv_bmissthreshold) {
ieee80211_beacon_miss(ic);
}
-
}
static int
@@ -5491,6 +5501,9 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in,
/* for non-data, use the lowest supported rate */
ridx = min_ridx;
*flags |= IWX_TX_FLAGS_CMD_RATE;
+ } else if (ni->ni_flags & IEEE80211_NODE_VHT) {
+ /* TODO: VHT - the ridx / rate array doesn't have VHT rates yet */
+ ridx = iwx_min_basic_rate(ic);
} else if (ni->ni_flags & IEEE80211_NODE_HT) {
ridx = iwx_mcs2ridx[ieee80211_node_get_txrate_dot11rate(ni)
& ~IEEE80211_RATE_MCS];
@@ -5622,6 +5635,8 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
struct mbuf *m1;
size_t txcmd_size;
+ IWX_ASSERT_LOCKED(sc);
+
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
@@ -7308,97 +7323,107 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in)
return iwx_rs_init_v3(sc, in);
}
-static void
-iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif)
+
+/**
+ * @brief Turn the given TX rate control notification into an ieee80211_node_txrate
+ *
+ * This populates the given txrate node with the TX rate control notification.
+ *
+ * @param sc driver softc
+ * @param notif firmware notification
+ * @param ni ieee80211_node update
+ * @returns true if updated, false if not
+ */
+static bool
+iwx_rs_update_node_txrate(struct iwx_softc *sc,
+ const struct iwx_tlc_update_notif *notif, struct ieee80211_node *ni)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct ieee80211_node *ni = (void *)vap->iv_bss;
+ /* XXX TODO: create an inline function in if_iwxreg.h? */
+ static int cck_idx_to_rate[] = { 2, 4, 11, 22, 2, 2, 2, 2 };
+ static int ofdm_idx_to_rate[] = { 12, 18, 24, 36, 48, 72, 96, 108 };
- struct ieee80211_rateset *rs = &ni->ni_rates;
uint32_t rate_n_flags;
- uint8_t plcp, rval;
- int i, cmd_ver, rate_n_flags_ver2 = 0;
-
- if (notif->sta_id != IWX_STATION_ID ||
- (le32toh(notif->flags) & IWX_TLC_NOTIF_FLAG_RATE) == 0)
- return;
+ uint32_t type;
+ /* Extract the rate and command version */
rate_n_flags = le32toh(notif->rate);
+ if (sc->sc_rate_n_flags_version != 2) {
+ net80211_ic_printf(ic,
+ "%s: unsupported rate_n_flags version (%d)\n",
+ __func__,
+ sc->sc_rate_n_flags_version);
+ return (false);
+ }
+
if (sc->sc_debug & IWX_DEBUG_TXRATE)
print_ratenflags(__func__, __LINE__,
rate_n_flags, sc->sc_rate_n_flags_version);
- cmd_ver = iwx_lookup_notif_ver(sc, IWX_DATA_PATH_GROUP,
- IWX_TLC_MNG_UPDATE_NOTIF);
- if (cmd_ver != IWX_FW_CMD_VER_UNKNOWN && cmd_ver >= 3)
- rate_n_flags_ver2 = 1;
-
- if (rate_n_flags_ver2) {
- uint32_t mod_type = (rate_n_flags & IWX_RATE_MCS_MOD_TYPE_MSK);
- if (mod_type == IWX_RATE_MCS_HT_MSK) {
-
- ieee80211_node_set_txrate_dot11rate(ni,
- IWX_RATE_HT_MCS_INDEX(rate_n_flags) |
- IEEE80211_RATE_MCS);
- IWX_DPRINTF(sc, IWX_DEBUG_TXRATE,
- "%s:%d new MCS: %d rate_n_flags: %x\n",
- __func__, __LINE__,
- ieee80211_node_get_txrate_dot11rate(ni) & ~IEEE80211_RATE_MCS,
- rate_n_flags);
- return;
- }
- } else {
- if (rate_n_flags & IWX_RATE_MCS_HT_MSK_V1) {
- ieee80211_node_set_txrate_dot11rate(ni,
- rate_n_flags & (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 |
- IWX_RATE_HT_MCS_NSS_MSK_V1));
-
- IWX_DPRINTF(sc, IWX_DEBUG_TXRATE,
- "%s:%d new MCS idx: %d rate_n_flags: %x\n",
- __func__, __LINE__,
- ieee80211_node_get_txrate_dot11rate(ni), rate_n_flags);
- return;
- }
+ type = (rate_n_flags & IWX_RATE_MCS_MOD_TYPE_MSK);
+ switch (type) {
+ case IWX_RATE_MCS_CCK_MSK:
+ ieee80211_node_set_txrate_dot11rate(ni,
+ cck_idx_to_rate[rate_n_flags & IWX_RATE_LEGACY_RATE_MSK]);
+ return (true);
+ case IWX_RATE_MCS_LEGACY_OFDM_MSK:
+ ieee80211_node_set_txrate_dot11rate(ni,
+ ofdm_idx_to_rate[rate_n_flags & IWX_RATE_LEGACY_RATE_MSK]);
+ return (true);
+ case IWX_RATE_MCS_HT_MSK:
+ /*
+ * TODO: the current API doesn't include channel width
+ * and other flags, so we can't accurately store them yet!
+ *
+ * channel width: (flags & IWX_RATE_MCS_CHAN_WIDTH_MSK)
+ * >> IWX_RATE_MCS_CHAN_WIDTH_POS)
+ * LDPC: (flags & (1 << 16))
+ */
+ ieee80211_node_set_txrate_ht_mcsrate(ni,
+ IWX_RATE_HT_MCS_INDEX(rate_n_flags));
+ return (true);
+ case IWX_RATE_MCS_VHT_MSK:
+ /* TODO: same comment on channel width, etc above */
+ ieee80211_node_set_txrate_vht_rate(ni,
+ IWX_RATE_VHT_MCS_CODE(rate_n_flags),
+ IWX_RATE_VHT_MCS_NSS(rate_n_flags));
+ return (true);
+ default:
+ net80211_ic_printf(ic,
+ "%s: unsupported chosen rate type in "
+ "IWX_RATE_MCS_MOD_TYPE (%d)\n", __func__,
+ type >> IWX_RATE_MCS_MOD_TYPE_POS);
+ return (false);
}
- if (rate_n_flags_ver2) {
- const struct ieee80211_rateset *rs;
- uint32_t ridx = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK);
- if (rate_n_flags & IWX_RATE_MCS_LEGACY_OFDM_MSK)
- rs = &ieee80211_std_rateset_11a;
- else
- rs = &ieee80211_std_rateset_11b;
- if (ridx < rs->rs_nrates)
- rval = (rs->rs_rates[ridx] & IEEE80211_RATE_VAL);
- else
- rval = 0;
- } else {
- plcp = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1);
+ /* Default: if we get here, we didn't successfully update anything */
+ return (false);
+}
- rval = 0;
- for (i = IWX_RATE_1M_INDEX; i < nitems(iwx_rates); i++) {
- if (iwx_rates[i].plcp == plcp) {
- rval = iwx_rates[i].rate;
- break;
- }
- }
- }
+/**
+ * @brief Process a firmware rate control update and update net80211.
+ *
+ * Since firmware is doing rate control, this just needs to update
+ * the txrate in the ieee80211_node entry.
+ */
+static void
+iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ /* XXX TODO: get a node ref! */
+ struct ieee80211_node *ni = (void *)vap->iv_bss;
- if (rval) {
- uint8_t rv;
- for (i = 0; i < rs->rs_nrates; i++) {
- rv = rs->rs_rates[i] & IEEE80211_RATE_VAL;
- if (rv == rval) {
- ieee80211_node_set_txrate_dot11rate(ni, i);
- break;
- }
- }
- IWX_DPRINTF(sc, IWX_DEBUG_TXRATE,
- "%s:%d new rate %d\n", __func__, __LINE__,
- ieee80211_node_get_txrate_dot11rate(ni));
- }
+ /*
+ * For now the iwx driver only supports a single vdev with a single
+ * node; it doesn't yet support ibss/hostap/multiple vdevs.
+ */
+ if (notif->sta_id != IWX_STATION_ID ||
+ (le32toh(notif->flags) & IWX_TLC_NOTIF_FLAG_RATE) == 0)
+ return;
+
+ iwx_rs_update_node_txrate(sc, notif, ni);
}
static int
@@ -8526,6 +8551,8 @@ iwx_start(struct iwx_softc *sc)
struct ieee80211_node *ni;
struct mbuf *m;
+ IWX_ASSERT_LOCKED(sc);
+
while (sc->qfullmsk == 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (iwx_tx(sc, m, ni) != 0) {
@@ -8985,10 +9012,10 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf *ml)
break;
case IWX_MISSED_BEACONS_NOTIFICATION:
+ IWX_DPRINTF(sc, IWX_DEBUG_BEACON,
+ "%s: IWX_MISSED_BEACONS_NOTIFICATION\n",
+ __func__);
iwx_rx_bmiss(sc, pkt, data);
- DPRINTF(("%s: IWX_MISSED_BEACONS_NOTIFICATION\n",
- __func__));
- ieee80211_beacon_miss(ic);
break;
case IWX_MFUART_LOAD_NOTIFICATION:
diff --git a/sys/dev/iwx/if_iwxreg.h b/sys/dev/iwx/if_iwxreg.h
index 6755b93fa0ba..f3d1f078b48e 100644
--- a/sys/dev/iwx/if_iwxreg.h
+++ b/sys/dev/iwx/if_iwxreg.h
@@ -5176,6 +5176,10 @@ enum {
#define IWX_RATE_HT_MCS_INDEX(r) ((((r) & IWX_RATE_MCS_NSS_MSK) >> 1) | \
((r) & IWX_RATE_HT_MCS_CODE_MSK))
+#define IWX_RATE_VHT_MCS_CODE(r) ((r) & IWX_RATE_HT_MCS_CODE_MSK)
+#define IWX_RATE_VHT_MCS_NSS(r) \
+ ((((r) & IWX_RATE_MCS_NSS_MSK) == 0) >> IWX_RATE_MCS_NSS_POS)
+
/* Bits 7-5: reserved */
/*
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 9e43a4c1909f..cde98cb62cef 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -240,6 +240,7 @@ struct pci_quirk {
#define PCI_QUIRK_DISABLE_MSIX 5 /* MSI-X doesn't work */
#define PCI_QUIRK_MSI_INTX_BUG 6 /* PCIM_CMD_INTxDIS disables MSI */
#define PCI_QUIRK_REALLOC_BAR 7 /* Can't allocate memory at the default address */
+#define PCI_QUIRK_DISABLE_FLR 8 /* Function-Level Reset (FLR) not working. */
int arg1;
int arg2;
};
@@ -319,6 +320,13 @@ static const struct pci_quirk pci_quirks[] = {
* expected place.
*/
{ 0x98741002, PCI_QUIRK_REALLOC_BAR, 0, 0 },
+
+ /*
+ * With some MediaTek mt76 WiFi FLR does not work despite advertised.
+ */
+ { 0x061614c3, PCI_QUIRK_DISABLE_FLR, 0, 0 }, /* mt76 7922 */
+
+ /* end of table */
{ 0 }
};
@@ -6740,6 +6748,8 @@ pcie_flr(device_t dev, u_int max_delay, bool force)
if (!(pci_read_config(dev, cap + PCIER_DEVICE_CAP, 4) & PCIEM_CAP_FLR))
return (false);
+ if (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_FLR))
+ return (false);
/*
* Disable busmastering to prevent generation of new
diff --git a/sys/dev/vmware/vmxnet3/if_vmx.c b/sys/dev/vmware/vmxnet3/if_vmx.c
index 62b5f313a137..1a314ca6660e 100644
--- a/sys/dev/vmware/vmxnet3/if_vmx.c
+++ b/sys/dev/vmware/vmxnet3/if_vmx.c
@@ -2056,7 +2056,12 @@ vmxnet3_update_admin_status(if_ctx_t ctx)
struct vmxnet3_softc *sc;
sc = iflib_get_softc(ctx);
- if (sc->vmx_ds->event != 0)
+ /*
+ * iflib may invoke this routine before vmxnet3_attach_post() has
+ * run, which is before the top level shared data area is
+ * initialized and the device made aware of it.
+ */
+ if (sc->vmx_ds != NULL && sc->vmx_ds->event != 0)
vmxnet3_evintr(sc);
vmxnet3_refresh_host_stats(sc);
diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c
index e1b2e08c3f10..c599db56bf95 100644
--- a/sys/dev/watchdog/watchdog.c
+++ b/sys/dev/watchdog/watchdog.c
@@ -204,6 +204,7 @@ wd_valid_act(int act)
return true;
}
+#ifdef COMPAT_FREEBSD14
static int
wd_ioctl_patpat(caddr_t data)
{
@@ -223,6 +224,7 @@ wd_ioctl_patpat(caddr_t data)
return (wdog_kern_pat(u));
}
+#endif
static int
wd_get_time_left(struct thread *td, time_t *remainp)