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/ahci/ahci_pci.c46
-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
6 files changed, 135 insertions, 121 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/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c
index 82f56fc0d19e..2b4cb37275a6 100644
--- a/sys/dev/ahci/ahci_pci.c
+++ b/sys/dev/ahci/ahci_pci.c
@@ -467,28 +467,6 @@ ahci_ata_probe(device_t dev)
}
static int
-ahci_pci_read_msix_bars(device_t dev, uint8_t *table_bar, uint8_t *pba_bar)
-{
- int cap_offset = 0, ret;
- uint32_t val;
-
- if ((table_bar == NULL) || (pba_bar == NULL))
- return (EINVAL);
-
- ret = pci_find_cap(dev, PCIY_MSIX, &cap_offset);
- if (ret != 0)
- return (EINVAL);
-
- val = pci_read_config(dev, cap_offset + PCIR_MSIX_TABLE, 4);
- *table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
-
- val = pci_read_config(dev, cap_offset + PCIR_MSIX_PBA, 4);
- *pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
-
- return (0);
-}
-
-static int
ahci_pci_attach(device_t dev)
{
struct ahci_controller *ctlr = device_get_softc(dev);
@@ -496,7 +474,6 @@ ahci_pci_attach(device_t dev)
uint32_t devid = pci_get_devid(dev);
uint8_t revid = pci_get_revid(dev);
int msi_count, msix_count;
- uint8_t table_bar = 0, pba_bar = 0;
uint32_t caps, pi;
msi_count = pci_msi_count(dev);
@@ -584,20 +561,11 @@ ahci_pci_attach(device_t dev)
if (ctlr->quirks & AHCI_Q_NOMSIX)
msix_count = 0;
- /* Read MSI-x BAR IDs if supported */
- if (msix_count > 0) {
- error = ahci_pci_read_msix_bars(dev, &table_bar, &pba_bar);
- if (error == 0) {
- ctlr->r_msix_tab_rid = table_bar;
- ctlr->r_msix_pba_rid = pba_bar;
- } else {
- /* Failed to read BARs, disable MSI-x */
- msix_count = 0;
- }
- }
-
/* Allocate resources for MSI-x table and PBA */
if (msix_count > 0) {
+ ctlr->r_msix_tab_rid = pci_msix_table_bar(dev);
+ ctlr->r_msix_pba_rid = pci_msix_pba_bar(dev);
+
/*
* Allocate new MSI-x table only if not
* allocated before.
@@ -608,8 +576,8 @@ ahci_pci_attach(device_t dev)
ctlr->r_msix_table = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&ctlr->r_msix_tab_rid, RF_ACTIVE);
if (ctlr->r_msix_table == NULL) {
- ahci_free_mem(dev);
- return (ENXIO);
+ msix_count = 0;
+ goto no_msix;
}
}
@@ -624,12 +592,12 @@ ahci_pci_attach(device_t dev)
ctlr->r_msix_pba = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&ctlr->r_msix_pba_rid, RF_ACTIVE);
if (ctlr->r_msix_pba == NULL) {
- ahci_free_mem(dev);
- return (ENXIO);
+ msix_count = 0;
}
}
}
+no_msix:
pci_enable_busmaster(dev);
/* Reset controller */
if ((error = ahci_pci_ctlr_reset(dev)) != 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);