diff options
author | attilio <attilio@FreeBSD.org> | 2011-05-05 14:05:29 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2011-05-05 14:05:29 +0000 |
commit | d3d3db9bac709a7fa4319bf5e8c8fb4e05918772 (patch) | |
tree | 1f3fc48f78abc0f826bc204651c01b9f8bbaed60 /sys | |
parent | f756d5bed6346f4902b1da276e52098882a7a66b (diff) | |
parent | 1e6b02c145b56555ee32db7471bf964bde2eade9 (diff) | |
download | FreeBSD-src-d3d3db9bac709a7fa4319bf5e8c8fb4e05918772.zip FreeBSD-src-d3d3db9bac709a7fa4319bf5e8c8fb4e05918772.tar.gz |
MFC
Diffstat (limited to 'sys')
31 files changed, 1204 insertions, 217 deletions
diff --git a/sys/dev/ath/ath_hal/ar5416/ar2133.c b/sys/dev/ath/ath_hal/ar5416/ar2133.c index f8f4df4..f92ea00 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar2133.c +++ b/sys/dev/ath/ath_hal/ar5416/ar2133.c @@ -165,7 +165,7 @@ ar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) } } else if ((freq % 20) == 0 && freq >= 5120) { channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); - if (AR_SREV_SOWL_10_OR_LATER(ah)) + if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) aModeRefSel = ath_hal_reverseBits(3, 2); else aModeRefSel = ath_hal_reverseBits(1, 2); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index f486ca6..03a4ee6 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -620,9 +620,9 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) HALDEBUG(ah, HAL_DEBUG_NFCAL, "CCA: "); for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { - /* Don't write to EXT radio CCA registers */ + /* Don't write to EXT radio CCA registers unless in HT/40 mode */ /* XXX this check should really be cleaner! */ - if (i >= 3 && !IEEE80211_IS_CHAN_HT40(chan)) + if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) continue; if (chainmask & (1 << i)) { @@ -670,6 +670,12 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) * of next noise floor calibration the baseband does. */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) + + /* Don't write to EXT radio CCA registers unless in HT/40 mode */ + /* XXX this check should really be cleaner! */ + if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) + continue; + if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; @@ -701,10 +707,12 @@ ar5416InitNfHistBuff(struct ar5212NfCalHist *h) * Update the noise floor buffer as a ring buffer */ static void -ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray) +ar5416UpdateNFHistBuff(struct ath_hal *ah, struct ar5212NfCalHist *h, + int16_t *nfarray) { int i; + /* XXX TODO: don't record nfarray[] entries for inactive chains */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; @@ -814,7 +822,7 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) } ichan->privFlags |= CHANNEL_MIMO_NF_VALID; - ar5416UpdateNFHistBuff(AH5416(ah)->ah_cal.nfCalHist, nfarray); + ar5416UpdateNFHistBuff(ah, AH5416(ah)->ah_cal.nfCalHist, nfarray); ichan->rawNoiseFloor = nf; } return nf; diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index 95bd966..4917caa 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -251,7 +251,12 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); /* Restore previous led state */ - OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState); + if (AR_SREV_HOWL(ah)) + OS_REG_WRITE(ah, AR_MAC_LED, + AR_MAC_LED_ASSOC_ACTIVE | AR_CFG_SCLK_32KHZ); + else + OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | + saveLedState); /* Restore previous antenna */ OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); @@ -332,6 +337,19 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; + if (AR_SREV_HOWL(ah)) { + /* + * Enable the MBSSID block-ack fix for HOWL. + * This feature is only supported on Howl 1.4, but it is safe to + * set bit 22 of STA_ID1 on other Howl revisions (1.1, 1.2, 1.3), + * since bit 22 is unused in those Howl revisions. + */ + unsigned int reg; + reg = (OS_REG_READ(ah, AR_STA_ID1) | (1<<22)); + OS_REG_WRITE(ah,AR_STA_ID1, reg); + ath_hal_printf(ah, "MBSSID Set bit 22 of AR_STA_ID 0x%x\n", reg); + } + HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); OS_MARK(ah, AH_MARK_RESET_DONE, 0); @@ -1205,7 +1223,11 @@ ar5416SetReset(struct ath_hal *ah, int type) #endif /* AH_SUPPORT_AR9130 */ OS_REG_WRITE(ah, AR_RTC_RC, rst_flags); - OS_DELAY(50); + + if (AR_SREV_HOWL(ah)) + OS_DELAY(10000); + else + OS_DELAY(100); /* * Clear resets and force wakeup diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h index 6fc5227..96903e4 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h @@ -199,6 +199,12 @@ #define AR_RXCFG_DMASZ_512B 7 /* MAC Led registers */ +#define AR_CFG_SCLK_RATE_IND 0x00000003 /* sleep clock indication */ +#define AR_CFG_SCLK_RATE_IND_S 0 +#define AR_CFG_SCLK_32MHZ 0x00000000 /* Sleep clock rate */ +#define AR_CFG_SCLK_4MHZ 0x00000001 /* Sleep clock rate */ +#define AR_CFG_SCLK_1MHZ 0x00000002 /* Sleep clock rate */ +#define AR_CFG_SCLK_32KHZ 0x00000003 /* Sleep clock rate */ #define AR_MAC_LED_BLINK_SLOW 0x00000008 /* LED slowest blink rate mode */ #define AR_MAC_LED_BLINK_THRESH_SEL 0x00000070 /* LED blink threshold select */ #define AR_MAC_LED_MODE 0x00000380 /* LED mode select */ @@ -619,56 +625,83 @@ #define AR_XSREV_REVISION_KITE_11 1 /* Kite 1.1 */ #define AR_XSREV_REVISION_KITE_12 2 /* Kite 1.2 */ +/* Owl (AR5416) */ #define AR_SREV_OWL(_ah) \ ((AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) || \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE)) #define AR_SREV_OWL_20_OR_LATER(_ah) \ - ((AR_SREV_OWL(_ah) && AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_20) || \ - AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + ((AR_SREV_OWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_20) || \ + AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + #define AR_SREV_OWL_22_OR_LATER(_ah) \ - ((AR_SREV_OWL(_ah) && AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_22) || \ - AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + ((AR_SREV_OWL(_ah) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_OWL_22) || \ + AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_HOWL) + +/* Howl (AR9130) */ #define AR_SREV_HOWL(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_HOWL) + #define AR_SREV_9100(_ah) AR_SREV_HOWL(_ah) +/* Sowl (AR9160) */ + #define AR_SREV_SOWL(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_SOWL) + #define AR_SREV_SOWL_10_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_SOWL) + #define AR_SREV_SOWL_11(_ah) \ (AR_SREV_SOWL(_ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_SOWL_11) +/* Merlin (AR9280) */ + #define AR_SREV_MERLIN(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_MERLIN) + #define AR_SREV_MERLIN_10_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN) + #define AR_SREV_MERLIN_20(_ah) \ (AR_SREV_MERLIN(_ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_MERLIN_20) + #define AR_SREV_MERLIN_20_OR_LATER(_ah) \ - (AR_SREV_MERLIN_20(_ah) || \ - AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_MERLIN) + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_MERLIN) || \ + (AR_SREV_MERLIN((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_MERLIN_20)) + +/* Kite (AR9285) */ #define AR_SREV_KITE(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion == AR_XSREV_VERSION_KITE) + #define AR_SREV_KITE_10_OR_LATER(_ah) \ (AH_PRIVATE((_ah))->ah_macVersion >= AR_XSREV_VERSION_KITE) + #define AR_SREV_KITE_11(_ah) \ (AR_SREV_KITE(ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KITE_11) + #define AR_SREV_KITE_11_OR_LATER(_ah) \ - (AR_SREV_KITE_11(_ah) || \ - AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_11) + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_KITE) || \ + (AR_SREV_KITE((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_11)) + #define AR_SREV_KITE_12(_ah) \ (AR_SREV_KITE(ah) && \ AH_PRIVATE((_ah))->ah_macRev == AR_XSREV_REVISION_KITE_12) + #define AR_SREV_KITE_12_OR_LATER(_ah) \ - (AR_SREV_KITE_12(_ah) || \ - AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_12) + ((AH_PRIVATE((_ah))->ah_macVersion > AR_XSREV_VERSION_KITE) || \ + (AR_SREV_KITE((_ah)) && \ + AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KITE_12)) + #define AR_SREV_9285E_20(_ah) \ (AR_SREV_KITE_12_OR_LATER(_ah) && \ ((OS_REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 76496aa..ed79ba3 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -214,9 +214,15 @@ static const struct bge_type { { BCOM_VENDORID, BCOM_DEVICEID_BCM5906 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5906M }, { BCOM_VENDORID, BCOM_DEVICEID_BCM57760 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM57761 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM57765 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM57780 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM57781 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM57785 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM57788 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM57790 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM57791 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM57795 }, { SK_VENDORID, SK_DEVICEID_ALTIMA }, @@ -307,6 +313,8 @@ static const struct bge_revision { { BGE_CHIPID_BCM5787_A2, "BCM5754/5787 A2" }, { BGE_CHIPID_BCM5906_A1, "BCM5906 A1" }, { BGE_CHIPID_BCM5906_A2, "BCM5906 A2" }, + { BGE_CHIPID_BCM57765_A0, "BCM57765 A0" }, + { BGE_CHIPID_BCM57765_B0, "BCM57765 B0" }, { BGE_CHIPID_BCM57780_A0, "BCM57780 A0" }, { BGE_CHIPID_BCM57780_A1, "BCM57780 A1" }, @@ -335,6 +343,7 @@ static const struct bge_revision const bge_majorrevs[] = { /* 5754 and 5787 share the same ASIC ID */ { BGE_ASICREV_BCM5787, "unknown BCM5754/5787" }, { BGE_ASICREV_BCM5906, "unknown BCM5906" }, + { BGE_ASICREV_BCM57765, "unknown BCM57765" }, { BGE_ASICREV_BCM57780, "unknown BCM57780" }, { BGE_ASICREV_BCM5717, "unknown BCM5717" }, @@ -1467,8 +1476,11 @@ bge_chipinit(struct bge_softc *sc) if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || sc->bge_asicrev == BGE_ASICREV_BCM5704) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; - if (BGE_IS_5717_PLUS(sc)) + if (BGE_IS_5717_PLUS(sc)) { dma_rw_ctl &= ~BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT; + if (sc->bge_chipid == BGE_CHIPID_BCM57765_A0) + dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK; + } pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); /* @@ -1552,7 +1564,8 @@ bge_blockinit(struct bge_softc *sc) } /* Configure mbuf pool watermarks */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5717) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5717 || + sc->bge_asicrev == BGE_ASICREV_BCM57765) { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); if (sc->bge_ifp->if_mtu > ETHERMTU) { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e); @@ -1819,7 +1832,8 @@ bge_blockinit(struct bge_softc *sc) limit = 16; } else if (!BGE_IS_5705_PLUS(sc)) limit = BGE_RX_RINGS_MAX; - else if (sc->bge_asicrev == BGE_ASICREV_BCM5755) + else if (sc->bge_asicrev == BGE_ASICREV_BCM5755 || + sc->bge_asicrev == BGE_ASICREV_BCM57765) limit = 4; else limit = 1; @@ -2180,6 +2194,15 @@ bge_probe(device_t dev) id = pci_read_config(dev, BGE_PCI_GEN2_PRODID_ASICREV, 4); break; + case BCOM_DEVICEID_BCM57761: + case BCOM_DEVICEID_BCM57765: + case BCOM_DEVICEID_BCM57781: + case BCOM_DEVICEID_BCM57785: + case BCOM_DEVICEID_BCM57791: + case BCOM_DEVICEID_BCM57795: + id = pci_read_config(dev, + BGE_PCI_GEN15_PRODID_ASICREV, 4); + break; default: id = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4); @@ -2694,6 +2717,15 @@ bge_attach(device_t dev) sc->bge_chipid = pci_read_config(dev, BGE_PCI_GEN2_PRODID_ASICREV, 4); break; + case BCOM_DEVICEID_BCM57761: + case BCOM_DEVICEID_BCM57765: + case BCOM_DEVICEID_BCM57781: + case BCOM_DEVICEID_BCM57785: + case BCOM_DEVICEID_BCM57791: + case BCOM_DEVICEID_BCM57795: + sc->bge_chipid = pci_read_config(dev, + BGE_PCI_GEN15_PRODID_ASICREV, 4); + break; default: sc->bge_chipid = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4); @@ -2737,12 +2769,12 @@ bge_attach(device_t dev) * Don't enable Ethernet@WireSpeed for the 5700, 5906, or the * 5705 A0 and A1 chips. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5700 && - sc->bge_asicrev != BGE_ASICREV_BCM5906 && - sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && - sc->bge_chipid != BGE_CHIPID_BCM5705_A1 && - !BGE_IS_5717_PLUS(sc)) - sc->bge_phy_flags |= BGE_PHY_WIRESPEED; + if (sc->bge_asicrev == BGE_ASICREV_BCM5700 || + (sc->bge_asicrev == BGE_ASICREV_BCM5705 && + (sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && + sc->bge_chipid != BGE_CHIPID_BCM5705_A1)) || + sc->bge_asicrev == BGE_ASICREV_BCM5906) + sc->bge_phy_flags |= BGE_PHY_NO_WIRESPEED; if (bge_has_eaddr(sc)) sc->bge_flags |= BGE_FLAG_EADDR; @@ -2750,9 +2782,11 @@ bge_attach(device_t dev) /* Save chipset family. */ switch (sc->bge_asicrev) { case BGE_ASICREV_BCM5717: + sc->bge_flags |= BGE_FLAG_SHORT_DMA_BUG; + case BGE_ASICREV_BCM57765: sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS | BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO | - BGE_FLAG_SHORT_DMA_BUG | BGE_FLAG_JUMBO_FRAME; + BGE_FLAG_JUMBO_FRAME; break; case BGE_ASICREV_BCM5755: case BGE_ASICREV_BCM5761: @@ -2801,6 +2835,7 @@ bge_attach(device_t dev) sc->bge_asicrev != BGE_ASICREV_BCM5906 && sc->bge_asicrev != BGE_ASICREV_BCM5717 && sc->bge_asicrev != BGE_ASICREV_BCM5785 && + sc->bge_asicrev != BGE_ASICREV_BCM57765 && sc->bge_asicrev != BGE_ASICREV_BCM57780) { if (sc->bge_asicrev == BGE_ASICREV_BCM5755 || sc->bge_asicrev == BGE_ASICREV_BCM5761 || @@ -3466,6 +3501,9 @@ bge_reset(struct bge_softc *sc) device_printf(dev, "firmware handshake timed out, found 0x%08x\n", val); + /* BCM57765 A0 needs additional time before accessing. */ + if (sc->bge_chipid == BGE_CHIPID_BCM57765_A0) + DELAY(10 * 1000); /* XXX */ } /* @@ -3506,7 +3544,7 @@ bge_reset(struct bge_softc *sc) /* XXX: Broadcom Linux driver. */ if (sc->bge_flags & BGE_FLAG_PCIE && - sc->bge_asicrev != BGE_ASICREV_BCM5717 && + !BGE_IS_5717_PLUS(sc) && sc->bge_chipid != BGE_CHIPID_BCM5750_A0 && sc->bge_asicrev != BGE_ASICREV_BCM5785) { /* Enable Data FIFO protection. */ @@ -4739,7 +4777,10 @@ bge_init_locked(struct bge_softc *sc) * this number of frames, it will drop subsequent incoming * frames until the MBUF High Watermark is reached. */ - CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); + if (sc->bge_asicrev == BGE_ASICREV_BCM57765) + CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1); + else + CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); /* Clear MAC statistics. */ if (BGE_IS_5705_PLUS(sc)) diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h index b63dbfb..dffec31 100644 --- a/sys/dev/bge/if_bgereg.h +++ b/sys/dev/bge/if_bgereg.h @@ -223,6 +223,7 @@ #define BGE_PCI_ISR_MBX_LO 0xB4 #define BGE_PCI_PRODID_ASICREV 0xBC #define BGE_PCI_GEN2_PRODID_ASICREV 0xF4 +#define BGE_PCI_GEN15_PRODID_ASICREV 0xFC /* PCI Misc. Host control register */ #define BGE_PCIMISCCTL_CLEAR_INTA 0x00000001 @@ -318,6 +319,8 @@ #define BGE_CHIPID_BCM57780_A1 0x57780001 #define BGE_CHIPID_BCM5717_A0 0x05717000 #define BGE_CHIPID_BCM5717_B0 0x05717100 +#define BGE_CHIPID_BCM57765_A0 0x57785000 +#define BGE_CHIPID_BCM57765_B0 0x57785100 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 12) @@ -342,6 +345,7 @@ #define BGE_ASICREV_BCM5761 0x5761 #define BGE_ASICREV_BCM5784 0x5784 #define BGE_ASICREV_BCM5785 0x5785 +#define BGE_ASICREV_BCM57765 0x57785 #define BGE_ASICREV_BCM57780 0x57780 /* chip revisions */ @@ -381,6 +385,8 @@ #define BGE_PCIDMARWCTL_RD_CMD_SHIFT(x) ((x) << 24) #define BGE_PCIDMARWCTL_WR_CMD_SHIFT(x) ((x) << 28) +#define BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK 0x00000380 + #define BGE_PCI_READ_BNDRY_DISABLE 0x00000000 #define BGE_PCI_READ_BNDRY_16BYTES 0x00000100 #define BGE_PCI_READ_BNDRY_32BYTES 0x00000200 @@ -2298,9 +2304,15 @@ struct bge_status_block { #define BCOM_DEVICEID_BCM5906 0x1712 #define BCOM_DEVICEID_BCM5906M 0x1713 #define BCOM_DEVICEID_BCM57760 0x1690 +#define BCOM_DEVICEID_BCM57761 0x16B0 +#define BCOM_DEVICEID_BCM57765 0x16B4 #define BCOM_DEVICEID_BCM57780 0x1692 +#define BCOM_DEVICEID_BCM57781 0x16B1 +#define BCOM_DEVICEID_BCM57785 0x16B5 #define BCOM_DEVICEID_BCM57788 0x1691 #define BCOM_DEVICEID_BCM57790 0x1694 +#define BCOM_DEVICEID_BCM57791 0x16B2 +#define BCOM_DEVICEID_BCM57795 0x16B6 /* * Alteon AceNIC PCI vendor/device ID. @@ -2771,7 +2783,7 @@ struct bge_softc { #define BGE_FLAG_RX_ALIGNBUG 0x04000000 #define BGE_FLAG_SHORT_DMA_BUG 0x08000000 uint32_t bge_phy_flags; -#define BGE_PHY_WIRESPEED 0x00000001 +#define BGE_PHY_NO_WIRESPEED 0x00000001 #define BGE_PHY_ADC_BUG 0x00000002 #define BGE_PHY_5704_A0_BUG 0x00000004 #define BGE_PHY_JITTER_BUG 0x00000008 diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h index 85f4fae..fa58853 100644 --- a/sys/dev/cxgbe/offload.h +++ b/sys/dev/cxgbe/offload.h @@ -61,8 +61,10 @@ struct tid_info { union aopen_entry *atid_tab; unsigned int natids; + struct filter_entry *ftid_tab; unsigned int nftids; unsigned int ftid_base; + unsigned int ftids_in_use; union aopen_entry *afree; unsigned int atids_in_use; diff --git a/sys/dev/cxgbe/t4_ioctl.h b/sys/dev/cxgbe/t4_ioctl.h index 65e95cf..8f1d133 100644 --- a/sys/dev/cxgbe/t4_ioctl.h +++ b/sys/dev/cxgbe/t4_ioctl.h @@ -31,6 +31,9 @@ #ifndef __T4_IOCTL_H__ #define __T4_IOCTL_H__ +#include <sys/types.h> +#include <net/ethernet.h> + /* * Ioctl commands specific to this driver. */ @@ -38,6 +41,11 @@ enum { T4_GETREG = 0x40, /* read register */ T4_SETREG, /* write register */ T4_REGDUMP, /* dump of all registers */ + T4_GET_FILTER_MODE, /* get global filter mode */ + T4_SET_FILTER_MODE, /* set global filter mode */ + T4_GET_FILTER, /* get information about a filter */ + T4_SET_FILTER, /* program a filter */ + T4_DEL_FILTER, /* delete a filter */ }; struct t4_reg { @@ -53,7 +61,133 @@ struct t4_regdump { uint32_t *data; }; +/* + * A hardware filter is some valid combination of these. + */ +#define T4_FILTER_IPv4 0x1 /* IPv4 packet */ +#define T4_FILTER_IPv6 0x2 /* IPv6 packet */ +#define T4_FILTER_IP_SADDR 0x4 /* Source IP address or network */ +#define T4_FILTER_IP_DADDR 0x8 /* Destination IP address or network */ +#define T4_FILTER_IP_SPORT 0x10 /* Source IP port */ +#define T4_FILTER_IP_DPORT 0x20 /* Destination IP port */ +#define T4_FILTER_FCoE 0x40 /* Fibre Channel over Ethernet packet */ +#define T4_FILTER_PORT 0x80 /* Physical ingress port */ +#define T4_FILTER_OVLAN 0x100 /* Outer VLAN ID */ +#define T4_FILTER_IVLAN 0x200 /* Inner VLAN ID */ +#define T4_FILTER_IP_TOS 0x400 /* IPv4 TOS/IPv6 Traffic Class */ +#define T4_FILTER_IP_PROTO 0x800 /* IP protocol */ +#define T4_FILTER_ETH_TYPE 0x1000 /* Ethernet Type */ +#define T4_FILTER_MAC_IDX 0x2000 /* MPS MAC address match index */ +#define T4_FILTER_MPS_HIT_TYPE 0x4000 /* MPS match type */ +#define T4_FILTER_IP_FRAGMENT 0x8000 /* IP fragment */ + +/* Filter action */ +enum { + FILTER_PASS = 0, /* default */ + FILTER_DROP, + FILTER_SWITCH +}; + +/* 802.1q manipulation on FILTER_SWITCH */ +enum { + VLAN_NOCHANGE = 0, /* default */ + VLAN_REMOVE, + VLAN_INSERT, + VLAN_REWRITE +}; + +/* MPS match type */ +enum { + UCAST_EXACT = 0, /* exact unicast match */ + UCAST_HASH = 1, /* inexact (hashed) unicast match */ + MCAST_EXACT = 2, /* exact multicast match */ + MCAST_HASH = 3, /* inexact (hashed) multicast match */ + PROMISC = 4, /* no match but port is promiscuous */ + HYPPROMISC = 5, /* port is hypervisor-promisuous + not bcast */ + BCAST = 6, /* broadcast packet */ +}; + +/* Rx steering */ +enum { + DST_MODE_QUEUE, /* queue is directly specified by filter */ + DST_MODE_RSS_QUEUE, /* filter specifies RSS entry containing queue */ + DST_MODE_RSS, /* queue selected by default RSS hash lookup */ + DST_MODE_FILT_RSS /* queue selected by hashing in filter-specified + RSS subtable */ +}; + +struct t4_filter_tuple { + /* + * These are always available. + */ + uint8_t sip[16]; /* source IP address (IPv4 in [3:0]) */ + uint8_t dip[16]; /* destinatin IP address (IPv4 in [3:0]) */ + uint16_t sport; /* source port */ + uint16_t dport; /* destination port */ + + /* + * A combination of these (upto 36 bits) is available. TP_VLAN_PRI_MAP + * is used to select the global mode and all filters are limited to the + * set of fields allowed by the global mode. + */ + uint16_t ovlan; /* outer VLAN */ + uint16_t ivlan; /* inner VLAN */ + uint16_t ethtype; /* Ethernet type */ + uint8_t tos; /* TOS/Traffic Type */ + uint8_t proto; /* protocol type */ + uint32_t fcoe:1; /* FCoE packet */ + uint32_t iport:3; /* ingress port */ + uint32_t matchtype:3; /* MPS match type */ + uint32_t frag:1; /* fragmentation extension header */ + uint32_t macidx:9; /* exact match MAC index */ + uint32_t ivlan_vld:1; /* inner VLAN valid */ + uint32_t ovlan_vld:1; /* outer VLAN valid */ +}; + +struct t4_filter_specification { + uint32_t hitcnts:1; /* count filter hits in TCB */ + uint32_t prio:1; /* filter has priority over active/server */ + uint32_t type:1; /* 0 => IPv4, 1 => IPv6 */ + uint32_t action:2; /* drop, pass, switch */ + uint32_t rpttid:1; /* report TID in RSS hash field */ + uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */ + uint32_t iq:10; /* ingress queue */ + uint32_t maskhash:1; /* dirsteer=0: store RSS hash in TCB */ + uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */ + /* 1 => TCB contains IQ ID */ + + /* + * Switch proxy/rewrite fields. An ingress packet which matches a + * filter with "switch" set will be looped back out as an egress + * packet -- potentially with some Ethernet header rewriting. + */ + uint32_t eport:2; /* egress port to switch packet out */ + uint32_t newdmac:1; /* rewrite destination MAC address */ + uint32_t newsmac:1; /* rewrite source MAC address */ + uint32_t newvlan:2; /* rewrite VLAN Tag */ + uint8_t dmac[ETHER_ADDR_LEN]; /* new destination MAC address */ + uint8_t smac[ETHER_ADDR_LEN]; /* new source MAC address */ + uint16_t vlan; /* VLAN Tag to insert */ + + /* + * Filter rule value/mask pairs. + */ + struct t4_filter_tuple val; + struct t4_filter_tuple mask; +}; + +struct t4_filter { + uint32_t idx; + uint64_t hits; + struct t4_filter_specification fs; +}; + #define CHELSIO_T4_GETREG _IOWR('f', T4_GETREG, struct t4_reg) #define CHELSIO_T4_SETREG _IOW('f', T4_SETREG, struct t4_reg) #define CHELSIO_T4_REGDUMP _IOWR('f', T4_REGDUMP, struct t4_regdump) +#define CHELSIO_T4_GET_FILTER_MODE _IOWR('f', T4_GET_FILTER_MODE, uint32_t) +#define CHELSIO_T4_SET_FILTER_MODE _IOW('f', T4_SET_FILTER_MODE, uint32_t) +#define CHELSIO_T4_GET_FILTER _IOWR('f', T4_GET_FILTER, struct t4_filter) +#define CHELSIO_T4_SET_FILTER _IOW('f', T4_SET_FILTER, struct t4_filter) +#define CHELSIO_T4_DEL_FILTER _IOW('f', T4_DEL_FILTER, struct t4_filter) #endif diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index c61548a..9037318 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include "common/t4_hw.h" #include "common/common.h" +#include "common/t4_msg.h" #include "common/t4_regs.h" #include "common/t4_regs_values.h" #include "common/t4fw_interface.h" @@ -218,6 +219,11 @@ TUNABLE_INT("hw.cxgbe.interrupt_forwarding", &intr_fwd); SYSCTL_UINT(_hw_cxgbe, OID_AUTO, interrupt_forwarding, CTLFLAG_RDTUN, &intr_fwd, 0, "always use forwarded interrupts"); +static unsigned int filter_mode = HW_TPL_FR_MT_PR_IV_P_FC; +TUNABLE_INT("hw.cxgbe.filter_mode", &filter_mode); +SYSCTL_UINT(_hw_cxgbe, OID_AUTO, filter_mode, CTLFLAG_RDTUN, + &filter_mode, 0, "default global filter mode."); + struct intrs_and_queues { int intr_type; /* INTx, MSI, or MSI-X */ int nirq; /* Number of vectors */ @@ -228,6 +234,15 @@ struct intrs_and_queues { int nrxq1g; /* # of NIC rxq's for each 1G port */ }; +struct filter_entry { + uint32_t valid:1; /* filter allocated and valid */ + uint32_t locked:1; /* filter is administratively locked */ + uint32_t pending:1; /* filter action is pending firmware reply */ + uint32_t smtidx:8; /* Source MAC Table index for smac */ + + struct t4_filter_specification fs; +}; + enum { MEMWIN0_APERTURE = 2048, MEMWIN0_BASE = 0x1b800, @@ -280,6 +295,18 @@ static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS); static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS); static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS); static inline void txq_start(struct ifnet *, struct sge_txq *); +static uint32_t fconf_to_mode(uint32_t); +static uint32_t mode_to_fconf(uint32_t); +static uint32_t fspec_to_fconf(struct t4_filter_specification *); +static int get_filter_mode(struct adapter *, uint32_t *); +static int set_filter_mode(struct adapter *, uint32_t); +static int get_filter(struct adapter *, struct t4_filter *); +static int set_filter(struct adapter *, struct t4_filter *); +static int del_filter(struct adapter *, struct t4_filter *); +static void clear_filter(struct adapter *, struct filter_entry *); +static int set_filter_wr(struct adapter *, int); +static int del_filter_wr(struct adapter *, int); +void filter_rpl(struct adapter *, const struct cpl_set_tcb_rpl *); static int t4_mod_event(module_t, int, void *); struct t4_pciids { @@ -421,9 +448,12 @@ t4_attach(device_t dev) t4_sge_init(sc); - /* - * XXX: This is the place to call t4_set_filter_mode() - */ + t4_set_filter_mode(sc, filter_mode); + t4_set_reg_field(sc, A_TP_GLOBAL_CONFIG, + V_FIVETUPLELOOKUP(M_FIVETUPLELOOKUP), + V_FIVETUPLELOOKUP(M_FIVETUPLELOOKUP)); + t4_tp_wr_bits_indirect(sc, A_TP_INGRESS_CONFIG, F_CSUM_HAS_PSEUDO_HDR, + F_LOOKUPEVERYPKT); /* get basic stuff going */ rc = -t4_early_init(sc, sc->mbox); @@ -661,6 +691,7 @@ t4_detach(device_t dev) free(sc->sge.fiq, M_CXGBE); free(sc->sge.iqmap, M_CXGBE); free(sc->sge.eqmap, M_CXGBE); + free(sc->tids.ftid_tab, M_CXGBE); t4_destroy_dma_tag(sc); mtx_destroy(&sc->sc_lock); @@ -2699,6 +2730,481 @@ cxgbe_txq_start(void *arg, int count) TXQ_UNLOCK(txq); } +static uint32_t +fconf_to_mode(uint32_t fconf) +{ + uint32_t mode; + + mode = T4_FILTER_IPv4 | T4_FILTER_IPv6 | T4_FILTER_IP_SADDR | + T4_FILTER_IP_DADDR | T4_FILTER_IP_SPORT | T4_FILTER_IP_DPORT; + + if (fconf & F_FRAGMENTATION) + mode |= T4_FILTER_IP_FRAGMENT; + + if (fconf & F_MPSHITTYPE) + mode |= T4_FILTER_MPS_HIT_TYPE; + + if (fconf & F_MACMATCH) + mode |= T4_FILTER_MAC_IDX; + + if (fconf & F_ETHERTYPE) + mode |= T4_FILTER_ETH_TYPE; + + if (fconf & F_PROTOCOL) + mode |= T4_FILTER_IP_PROTO; + + if (fconf & F_TOS) + mode |= T4_FILTER_IP_TOS; + + if (fconf & F_VLAN) + mode |= T4_FILTER_IVLAN; + + if (fconf & F_VNIC_ID) + mode |= T4_FILTER_OVLAN; + + if (fconf & F_PORT) + mode |= T4_FILTER_PORT; + + if (fconf & F_FCOE) + mode |= T4_FILTER_FCoE; + + return (mode); +} + +static uint32_t +mode_to_fconf(uint32_t mode) +{ + uint32_t fconf = 0; + + if (mode & T4_FILTER_IP_FRAGMENT) + fconf |= F_FRAGMENTATION; + + if (mode & T4_FILTER_MPS_HIT_TYPE) + fconf |= F_MPSHITTYPE; + + if (mode & T4_FILTER_MAC_IDX) + fconf |= F_MACMATCH; + + if (mode & T4_FILTER_ETH_TYPE) + fconf |= F_ETHERTYPE; + + if (mode & T4_FILTER_IP_PROTO) + fconf |= F_PROTOCOL; + + if (mode & T4_FILTER_IP_TOS) + fconf |= F_TOS; + + if (mode & T4_FILTER_IVLAN) + fconf |= F_VLAN; + + if (mode & T4_FILTER_OVLAN) + fconf |= F_VNIC_ID; + + if (mode & T4_FILTER_PORT) + fconf |= F_PORT; + + if (mode & T4_FILTER_FCoE) + fconf |= F_FCOE; + + return (fconf); +} + +static uint32_t +fspec_to_fconf(struct t4_filter_specification *fs) +{ + uint32_t fconf = 0; + + if (fs->val.frag || fs->mask.frag) + fconf |= F_FRAGMENTATION; + + if (fs->val.matchtype || fs->mask.matchtype) + fconf |= F_MPSHITTYPE; + + if (fs->val.macidx || fs->mask.macidx) + fconf |= F_MACMATCH; + + if (fs->val.ethtype || fs->mask.ethtype) + fconf |= F_ETHERTYPE; + + if (fs->val.proto || fs->mask.proto) + fconf |= F_PROTOCOL; + + if (fs->val.tos || fs->mask.tos) + fconf |= F_TOS; + + if (fs->val.ivlan_vld || fs->mask.ivlan_vld) + fconf |= F_VLAN; + + if (fs->val.ovlan_vld || fs->mask.ovlan_vld) + fconf |= F_VNIC_ID; + + if (fs->val.iport || fs->mask.iport) + fconf |= F_PORT; + + if (fs->val.fcoe || fs->mask.fcoe) + fconf |= F_FCOE; + + return (fconf); +} + +static int +get_filter_mode(struct adapter *sc, uint32_t *mode) +{ + uint32_t fconf; + + t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &fconf, 1, + A_TP_VLAN_PRI_MAP); + + *mode = fconf_to_mode(fconf); + + return (0); +} + +static int +set_filter_mode(struct adapter *sc, uint32_t mode) +{ + uint32_t fconf; + int rc; + + fconf = mode_to_fconf(mode); + + ADAPTER_LOCK(sc); + if (IS_BUSY(sc)) { + rc = EAGAIN; + goto done; + } + + if (sc->tids.ftids_in_use > 0) { + rc = EBUSY; + goto done; + } + + rc = -t4_set_filter_mode(sc, fconf); +done: + ADAPTER_UNLOCK(sc); + return (rc); +} + +static int +get_filter(struct adapter *sc, struct t4_filter *t) +{ + int i, nfilters = sc->tids.nftids; + struct filter_entry *f; + + ADAPTER_LOCK_ASSERT_OWNED(sc); + + if (IS_BUSY(sc)) + return (EAGAIN); + + if (sc->tids.ftids_in_use == 0 || sc->tids.ftid_tab == NULL || + t->idx >= nfilters) { + t->idx = 0xffffffff; + return (0); + } + + f = &sc->tids.ftid_tab[t->idx]; + for (i = t->idx; i < nfilters; i++, f++) { + if (f->valid) { + t->idx = i; + t->fs = f->fs; + t->hits = 0; /* XXX implement */ + + return (0); + } + } + + t->idx = 0xffffffff; + return (0); +} + +static int +set_filter(struct adapter *sc, struct t4_filter *t) +{ + uint32_t fconf; + unsigned int nfilters, nports; + struct filter_entry *f; + int i; + + ADAPTER_LOCK_ASSERT_OWNED(sc); + + nfilters = sc->tids.nftids; + nports = sc->params.nports; + + if (nfilters == 0) + return (ENOTSUP); + + if (!(sc->flags & FULL_INIT_DONE)) + return (EAGAIN); + + if (t->idx >= nfilters) + return (EINVAL); + + /* Validate against the global filter mode */ + t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &fconf, 1, + A_TP_VLAN_PRI_MAP); + if ((fconf | fspec_to_fconf(&t->fs)) != fconf) + return (E2BIG); + + if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports) + return (EINVAL); + + if (t->fs.val.iport >= nports) + return (EINVAL); + + /* Can't specify an iq if not steering to it */ + if (!t->fs.dirsteer && t->fs.iq) + return (EINVAL); + + /* IPv6 filter idx must be 4 aligned */ + if (t->fs.type == 1 && + ((t->idx & 0x3) || t->idx + 4 >= nfilters)) + return (EINVAL); + + if (sc->tids.ftid_tab == NULL) { + KASSERT(sc->tids.ftids_in_use == 0, + ("%s: no memory allocated but filters_in_use > 0", + __func__)); + + sc->tids.ftid_tab = malloc(sizeof (struct filter_entry) * + nfilters, M_CXGBE, M_NOWAIT | M_ZERO); + if (sc->tids.ftid_tab == NULL) + return (ENOMEM); + } + + for (i = 0; i < 4; i++) { + f = &sc->tids.ftid_tab[t->idx + i]; + + if (f->pending || f->valid) + return (EBUSY); + if (f->locked) + return (EPERM); + + if (t->fs.type == 0) + break; + } + + f = &sc->tids.ftid_tab[t->idx]; + f->fs = t->fs; + + return set_filter_wr(sc, t->idx); +} + +static int +del_filter(struct adapter *sc, struct t4_filter *t) +{ + unsigned int nfilters; + struct filter_entry *f; + + ADAPTER_LOCK_ASSERT_OWNED(sc); + + if (IS_BUSY(sc)) + return (EAGAIN); + + nfilters = sc->tids.nftids; + + if (nfilters == 0) + return (ENOTSUP); + + if (sc->tids.ftid_tab == NULL || sc->tids.ftids_in_use == 0 || + t->idx >= nfilters) + return (EINVAL); + + if (!(sc->flags & FULL_INIT_DONE)) + return (EAGAIN); + + f = &sc->tids.ftid_tab[t->idx]; + + if (f->pending) + return (EBUSY); + if (f->locked) + return (EPERM); + + if (f->valid) { + t->fs = f->fs; /* extra info for the caller */ + return del_filter_wr(sc, t->idx); + } + + return (0); +} + +/* XXX: L2T */ +static void +clear_filter(struct adapter *sc, struct filter_entry *f) +{ + (void) sc; + bzero(f, sizeof (*f)); +} + +static int +set_filter_wr(struct adapter *sc, int fidx) +{ + int rc; + struct filter_entry *f = &sc->tids.ftid_tab[fidx]; + struct mbuf *m; + struct fw_filter_wr *fwr; + unsigned int ftid; + + ADAPTER_LOCK_ASSERT_OWNED(sc); + + if (f->fs.newdmac || f->fs.newvlan) + return (ENOTSUP); /* XXX: fix after L2T code */ + + ftid = sc->tids.ftid_base + fidx; + + m = m_gethdr(M_NOWAIT, MT_DATA); + if (m == NULL) + return (ENOMEM); + + fwr = mtod(m, struct fw_filter_wr *); + m->m_len = m->m_pkthdr.len = sizeof(*fwr); + bzero(fwr, sizeof (*fwr)); + + fwr->op_pkd = htobe32(V_FW_WR_OP(FW_FILTER_WR)); + fwr->len16_pkd = htobe32(FW_LEN16(*fwr)); + fwr->tid_to_iq = + htobe32(V_FW_FILTER_WR_TID(ftid) | + V_FW_FILTER_WR_RQTYPE(f->fs.type) | + V_FW_FILTER_WR_NOREPLY(0) | + V_FW_FILTER_WR_IQ(f->fs.iq)); + fwr->del_filter_to_l2tix = + htobe32(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) | + V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | + V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | + V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) | + V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) | + V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | + V_FW_FILTER_WR_DMAC(f->fs.newdmac) | + V_FW_FILTER_WR_SMAC(f->fs.newsmac) | + V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT || + f->fs.newvlan == VLAN_REWRITE) | + V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE || + f->fs.newvlan == VLAN_REWRITE) | + V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) | + V_FW_FILTER_WR_TXCHAN(f->fs.eport) | + V_FW_FILTER_WR_PRIO(f->fs.prio) | + V_FW_FILTER_WR_L2TIX(0)); /* XXX: L2T */ + fwr->ethtype = htobe16(f->fs.val.ethtype); + fwr->ethtypem = htobe16(f->fs.mask.ethtype); + fwr->frag_to_ovlan_vldm = + (V_FW_FILTER_WR_FRAG(f->fs.val.frag) | + V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) | + V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) | + V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) | + V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) | + V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld)); + fwr->smac_sel = 0; + fwr->rx_chan_rx_rpl_iq = htobe16(V_FW_FILTER_WR_RX_CHAN(0) | + V_FW_FILTER_WR_RX_RPL_IQ(sc->sge.fwq.abs_id)); + fwr->maci_to_matchtypem = + htobe32(V_FW_FILTER_WR_MACI(f->fs.val.macidx) | + V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) | + V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) | + V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) | + V_FW_FILTER_WR_PORT(f->fs.val.iport) | + V_FW_FILTER_WR_PORTM(f->fs.mask.iport) | + V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) | + V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype)); + fwr->ptcl = f->fs.val.proto; + fwr->ptclm = f->fs.mask.proto; + fwr->ttyp = f->fs.val.tos; + fwr->ttypm = f->fs.mask.tos; + fwr->ivlan = htobe16(f->fs.val.ivlan); + fwr->ivlanm = htobe16(f->fs.mask.ivlan); + fwr->ovlan = htobe16(f->fs.val.ovlan); + fwr->ovlanm = htobe16(f->fs.mask.ovlan); + bcopy(f->fs.val.dip, fwr->lip, sizeof (fwr->lip)); + bcopy(f->fs.mask.dip, fwr->lipm, sizeof (fwr->lipm)); + bcopy(f->fs.val.sip, fwr->fip, sizeof (fwr->fip)); + bcopy(f->fs.mask.sip, fwr->fipm, sizeof (fwr->fipm)); + fwr->lp = htobe16(f->fs.val.dport); + fwr->lpm = htobe16(f->fs.mask.dport); + fwr->fp = htobe16(f->fs.val.sport); + fwr->fpm = htobe16(f->fs.mask.sport); + if (f->fs.newsmac) + bcopy(f->fs.smac, fwr->sma, sizeof (fwr->sma)); + + f->pending = 1; + sc->tids.ftids_in_use++; + rc = t4_mgmt_tx(sc, m); + if (rc != 0) { + sc->tids.ftids_in_use--; + m_freem(m); + clear_filter(sc, f); + } + return (rc); +} + +static int +del_filter_wr(struct adapter *sc, int fidx) +{ + struct filter_entry *f = &sc->tids.ftid_tab[fidx]; + struct mbuf *m; + struct fw_filter_wr *fwr; + unsigned int rc, ftid; + + ADAPTER_LOCK_ASSERT_OWNED(sc); + + ftid = sc->tids.ftid_base + fidx; + + m = m_gethdr(M_NOWAIT, MT_DATA); + if (m == NULL) + return (ENOMEM); + + fwr = mtod(m, struct fw_filter_wr *); + m->m_len = m->m_pkthdr.len = sizeof(*fwr); + bzero(fwr, sizeof (*fwr)); + + t4_mk_filtdelwr(ftid, fwr, sc->sge.fwq.abs_id); + + f->pending = 1; + rc = t4_mgmt_tx(sc, m); + if (rc != 0) { + f->pending = 0; + m_freem(m); + } + return (rc); +} + +/* XXX move intr handlers to main.c and make this static */ +void +filter_rpl(struct adapter *sc, const struct cpl_set_tcb_rpl *rpl) +{ + unsigned int idx = GET_TID(rpl); + + if (idx >= sc->tids.ftid_base && + (idx -= sc->tids.ftid_base) < sc->tids.nftids) { + unsigned int rc = G_COOKIE(rpl->cookie); + struct filter_entry *f = &sc->tids.ftid_tab[idx]; + + if (rc == FW_FILTER_WR_FLT_DELETED) { + /* + * Clear the filter when we get confirmation from the + * hardware that the filter has been deleted. + */ + clear_filter(sc, f); + sc->tids.ftids_in_use--; + } else if (rc == FW_FILTER_WR_SMT_TBL_FULL) { + device_printf(sc->dev, + "filter %u setup failed due to full SMT\n", idx); + clear_filter(sc, f); + sc->tids.ftids_in_use--; + } else if (rc == FW_FILTER_WR_FLT_ADDED) { + f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff; + f->pending = 0; /* asynchronous setup completed */ + f->valid = 1; + } else { + /* + * Something went wrong. Issue a warning about the + * problem and clear everything out. + */ + device_printf(sc->dev, + "filter %u setup failed with error %u\n", idx, rc); + clear_filter(sc, f); + sc->tids.ftids_in_use--; + } + } +} + int t4_os_find_pci_capability(struct adapter *sc, int cap) { @@ -2873,6 +3379,27 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, free(buf, M_CXGBE); break; } + case CHELSIO_T4_GET_FILTER_MODE: + rc = get_filter_mode(sc, (uint32_t *)data); + break; + case CHELSIO_T4_SET_FILTER_MODE: + rc = set_filter_mode(sc, *(uint32_t *)data); + break; + case CHELSIO_T4_GET_FILTER: + ADAPTER_LOCK(sc); + rc = get_filter(sc, (struct t4_filter *)data); + ADAPTER_UNLOCK(sc); + break; + case CHELSIO_T4_SET_FILTER: + ADAPTER_LOCK(sc); + rc = set_filter(sc, (struct t4_filter *)data); + ADAPTER_UNLOCK(sc); + break; + case CHELSIO_T4_DEL_FILTER: + ADAPTER_LOCK(sc); + rc = del_filter(sc, (struct t4_filter *)data); + ADAPTER_UNLOCK(sc); + break; default: rc = EINVAL; } diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 05f0779..5440528 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -142,6 +142,8 @@ static int handle_sge_egr_update(struct adapter *, static int ctrl_tx(struct adapter *, struct sge_ctrlq *, struct mbuf *); +extern void filter_rpl(struct adapter *, const struct cpl_set_tcb_rpl *); + /* * Called on MOD_LOAD and fills up fl_buf_info[]. */ @@ -499,11 +501,8 @@ t4_intr_fwd(void *arg) iq_next(iq); } - if (ndesc_total > 0) { - t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), - V_CIDXINC(ndesc_pending) | V_INGRESSQID((u32)iq->cntxt_id) | - V_SEINTARM(iq->intr_params)); - } + t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(ndesc_pending) | + V_INGRESSQID((u32)iq->cntxt_id) | V_SEINTARM(iq->intr_params)); atomic_cmpset_32(&iq->state, IQS_BUSY, IQS_IDLE); } @@ -583,7 +582,9 @@ t4_evt_rx(void *arg) case CPL_SGE_EGR_UPDATE: handle_sge_egr_update(sc, (const void *)(rss + 1)); break; - + case CPL_SET_TCB_RPL: + filter_rpl(sc, (const void *) (rss + 1)); + break; default: device_printf(sc->dev, "can't handle CPL opcode %d.", rss->opcode); @@ -601,13 +602,16 @@ t4_evt_rx(void *arg) iq_next(iq); } - if (ndesc_total > 0) { - t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), - V_CIDXINC(ndesc_pending) | V_INGRESSQID(iq->cntxt_id) | - V_SEINTARM(iq->intr_params)); - } + t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(ndesc_pending) | + V_INGRESSQID(iq->cntxt_id) | V_SEINTARM(iq->intr_params)); } +#ifdef T4_PKT_TIMESTAMP +#define RX_COPY_THRESHOLD (MINCLSIZE - 8) +#else +#define RX_COPY_THRESHOLD MINCLSIZE +#endif + void t4_eth_rx(void *arg) { @@ -671,7 +675,22 @@ t4_eth_rx(void *arg) BUS_DMASYNC_POSTREAD); m_init(m0, NULL, 0, M_NOWAIT, MT_DATA, M_PKTHDR); - if (len < MINCLSIZE) { + +#ifdef T4_PKT_TIMESTAMP + *mtod(m0, uint64_t *) = + be64toh(ctrl->u.last_flit & 0xfffffffffffffff); + m0->m_data += 8; + + /* + * 60 bit timestamp value is *(uint64_t *)m0->m_pktdat. Note + * that it is in the leading free-space (see M_LEADINGSPACE) in + * the mbuf. The kernel can clobber it during a pullup, + * m_copymdata, etc. You need to make sure that the mbuf + * reaches you unmolested if you care about the timestamp. + */ +#endif + + if (len < RX_COPY_THRESHOLD) { /* copy data to mbuf, buffer will be recycled */ bcopy(sd->cl, mtod(m0, caddr_t), len); m0->m_len = len; diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index ef5fc27..4c07739 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -927,7 +927,7 @@ brgphy_reset(struct mii_softc *sc) brgphy_jumbo_settings(sc, ifp->if_mtu); - if (bge_sc->bge_phy_flags & BGE_PHY_WIRESPEED) + if ((bge_sc->bge_phy_flags & BGE_PHY_NO_WIRESPEED) == 0) brgphy_ethernet_wirespeed(sc); /* Enable Link LED on Dell boxes */ diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h index f007b70..6b66c1f 100644 --- a/sys/fs/nfs/nfsproto.h +++ b/sys/fs/nfs/nfsproto.h @@ -66,6 +66,14 @@ #define NFSV4_SMALLSTR 50 /* Strings small enough for stack */ /* Stat numbers for rpc returns (version 2, 3 and 4) */ +/* + * These numbers are hard-wired in the RFCs, so they can't be changed. + * The code currently assumes that the ones < 10000 are the same as + * sys/errno.h and that sys/errno.h will never go as high as 10000. + * If the value in sys/errno.h of any entry listed below is changed, + * the NFS code must be modified to do the mapping between them. + * (You can ignore NFSERR_WFLUSH, since it is never actually used.) + */ #define NFSERR_OK 0 #define NFSERR_PERM 1 #define NFSERR_NOENT 2 diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c index 2470a8c..0c3a4c9 100644 --- a/sys/fs/nfsclient/nfs_clport.c +++ b/sys/fs/nfsclient/nfs_clport.c @@ -838,21 +838,33 @@ void nfscl_loadsbinfo(struct nfsmount *nmp, struct nfsstatfs *sfp, void *statfs) { struct statfs *sbp = (struct statfs *)statfs; - nfsquad_t tquad; if (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) { sbp->f_bsize = NFS_FABLKSIZE; - tquad.qval = sfp->sf_tbytes; - sbp->f_blocks = (long)(tquad.qval / ((u_quad_t)NFS_FABLKSIZE)); - tquad.qval = sfp->sf_fbytes; - sbp->f_bfree = (long)(tquad.qval / ((u_quad_t)NFS_FABLKSIZE)); - tquad.qval = sfp->sf_abytes; - sbp->f_bavail = (long)(tquad.qval / ((u_quad_t)NFS_FABLKSIZE)); - tquad.qval = sfp->sf_tfiles; - sbp->f_files = (tquad.lval[0] & 0x7fffffff); - tquad.qval = sfp->sf_ffiles; - sbp->f_ffree = (tquad.lval[0] & 0x7fffffff); + sbp->f_blocks = sfp->sf_tbytes / NFS_FABLKSIZE; + sbp->f_bfree = sfp->sf_fbytes / NFS_FABLKSIZE; + /* + * Although sf_abytes is uint64_t and f_bavail is int64_t, + * the value after dividing by NFS_FABLKSIZE is small + * enough that it will fit in 63bits, so it is ok to + * assign it to f_bavail without fear that it will become + * negative. + */ + sbp->f_bavail = sfp->sf_abytes / NFS_FABLKSIZE; + sbp->f_files = sfp->sf_tfiles; + /* Since f_ffree is int64_t, clip it to 63bits. */ + if (sfp->sf_ffiles > INT64_MAX) + sbp->f_ffree = INT64_MAX; + else + sbp->f_ffree = sfp->sf_ffiles; } else if ((nmp->nm_flag & NFSMNT_NFSV4) == 0) { + /* + * The type casts to (int32_t) ensure that this code is + * compatible with the old NFS client, in that it will + * propagate bit31 to the high order bits. This may or may + * not be correct for NFSv2, but since it is a legacy + * environment, I'd rather retain backwards compatibility. + */ sbp->f_bsize = (int32_t)sfp->sf_bsize; sbp->f_blocks = (int32_t)sfp->sf_blocks; sbp->f_bfree = (int32_t)sfp->sf_bfree; diff --git a/sys/geom/cache/g_cache.c b/sys/geom/cache/g_cache.c index 01c7873..ca05f14 100644 --- a/sys/geom/cache/g_cache.c +++ b/sys/geom/cache/g_cache.c @@ -501,12 +501,6 @@ g_cache_create(struct g_class *mp, struct g_provider *pp, } gp = g_new_geomf(mp, md->md_name); - if (gp == NULL) { - G_CACHE_DEBUG(0, "Cannot create geom %s.", md->md_name); - return (NULL); - } - gp->softc = NULL; /* for a moment */ - sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); sc->sc_type = type; sc->sc_bshift = bshift; @@ -527,10 +521,6 @@ g_cache_create(struct g_class *mp, struct g_provider *pp, gp->dumpconf = g_cache_dumpconf; newpp = g_new_providerf(gp, "cache/%s", gp->name); - if (newpp == NULL) { - G_CACHE_DEBUG(0, "Cannot create provider cache/%s.", gp->name); - goto fail; - } newpp->sectorsize = pp->sectorsize; newpp->mediasize = pp->mediasize; if (type == G_CACHE_TYPE_AUTOMATIC) @@ -538,35 +528,20 @@ g_cache_create(struct g_class *mp, struct g_provider *pp, sc->sc_tail = BNO2OFF(OFF2BNO(newpp->mediasize, sc), sc); cp = g_new_consumer(gp); - if (cp == NULL) { - G_CACHE_DEBUG(0, "Cannot create consumer for %s.", gp->name); - goto fail; - } if (g_attach(cp, pp) != 0) { G_CACHE_DEBUG(0, "Cannot attach to provider %s.", pp->name); - goto fail; + g_destroy_consumer(cp); + g_destroy_provider(newpp); + mtx_destroy(&sc->sc_mtx); + g_free(sc); + g_destroy_geom(gp); + return (NULL); } g_error_provider(newpp, 0); G_CACHE_DEBUG(0, "Device %s created.", gp->name); callout_reset(&sc->sc_callout, g_cache_timeout * hz, g_cache_go, sc); return (gp); -fail: - if (cp != NULL) { - if (cp->provider != NULL) - g_detach(cp); - g_destroy_consumer(cp); - } - if (newpp != NULL) - g_destroy_provider(newpp); - if (gp != NULL) { - if (gp->softc != NULL) { - mtx_destroy(&sc->sc_mtx); - g_free(gp->softc); - } - g_destroy_geom(gp); - } - return (NULL); } static int diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index 10ee571..54e0fe0 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -547,8 +547,6 @@ g_concat_create(struct g_class *mp, const struct g_concat_metadata *md, } } gp = g_new_geomf(mp, "%s", md->md_name); - gp->softc = NULL; /* for a moment */ - sc = malloc(sizeof(*sc), M_CONCAT, M_WAITOK | M_ZERO); gp->start = g_concat_start; gp->spoiled = g_concat_orphan; diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 8edd147..8b22ee5 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -682,8 +682,6 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp, G_ELI_DEBUG(1, "Creating device %s%s.", bpp->name, G_ELI_SUFFIX); gp = g_new_geomf(mp, "%s%s", bpp->name, G_ELI_SUFFIX); - gp->softc = NULL; /* for a moment */ - sc = malloc(sizeof(*sc), M_ELI, M_WAITOK | M_ZERO); gp->start = g_eli_start; /* diff --git a/sys/geom/journal/g_journal.c b/sys/geom/journal/g_journal.c index 906a1e4..254ba92 100644 --- a/sys/geom/journal/g_journal.c +++ b/sys/geom/journal/g_journal.c @@ -2097,7 +2097,6 @@ g_journal_worker(void *arg) gp = sc->sc_geom; g_topology_lock(); pp = g_new_providerf(gp, "%s.journal", sc->sc_name); - KASSERT(pp != NULL, ("Cannot create %s.journal.", sc->sc_name)); pp->mediasize = sc->sc_mediasize; /* * There could be a problem when data provider and journal providers diff --git a/sys/geom/mountver/g_mountver.c b/sys/geom/mountver/g_mountver.c index bf2e8a6..c653090 100644 --- a/sys/geom/mountver/g_mountver.c +++ b/sys/geom/mountver/g_mountver.c @@ -248,10 +248,6 @@ g_mountver_create(struct gctl_req *req, struct g_class *mp, struct g_provider *p } } gp = g_new_geomf(mp, name); - if (gp == NULL) { - gctl_error(req, "Cannot create geom %s.", name); - return (ENOMEM); - } sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); mtx_init(&sc->sc_mtx, "gmountver", NULL, MTX_DEF); TAILQ_INIT(&sc->sc_queue); @@ -263,20 +259,10 @@ g_mountver_create(struct gctl_req *req, struct g_class *mp, struct g_provider *p gp->dumpconf = g_mountver_dumpconf; newpp = g_new_providerf(gp, gp->name); - if (newpp == NULL) { - gctl_error(req, "Cannot create provider %s.", name); - error = ENOMEM; - goto fail; - } newpp->mediasize = pp->mediasize; newpp->sectorsize = pp->sectorsize; cp = g_new_consumer(gp); - if (cp == NULL) { - gctl_error(req, "Cannot create consumer for %s.", gp->name); - error = ENOMEM; - goto fail; - } error = g_attach(cp, pp); if (error != 0) { gctl_error(req, "Cannot attach to provider %s.", pp->name); @@ -303,20 +289,13 @@ g_mountver_create(struct gctl_req *req, struct g_class *mp, struct g_provider *p G_MOUNTVER_DEBUG(0, "Device %s created.", gp->name); return (0); fail: - if (sc->sc_provider_name != NULL) - g_free(sc->sc_provider_name); - if (cp != NULL) { - if (cp->provider != NULL) - g_detach(cp); - g_destroy_consumer(cp); - } - if (newpp != NULL) - g_destroy_provider(newpp); - if (gp != NULL) { - if (gp->softc != NULL) - g_free(gp->softc); - g_destroy_geom(gp); - } + g_free(sc->sc_provider_name); + if (cp->provider != NULL) + g_detach(cp); + g_destroy_consumer(cp); + g_destroy_provider(newpp); + g_free(gp->softc); + g_destroy_geom(gp); return (error); } diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index 6c53f41..6720a87 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -293,9 +293,6 @@ g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md) } gp = g_new_geomf(mp, md->md_name); - if (gp == NULL) - goto fail; - sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); gp->softc = sc; gp->start = g_multipath_start; @@ -305,21 +302,12 @@ g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md) memcpy(sc->sc_name, md->md_name, sizeof (sc->sc_name)); pp = g_new_providerf(gp, "multipath/%s", md->md_name); - if (pp == NULL) - goto fail; /* limit the provider to not have it stomp on metadata */ pp->mediasize = md->md_size - md->md_sectorsize; pp->sectorsize = md->md_sectorsize; sc->pp = pp; g_error_provider(pp, 0); return (gp); -fail: - if (gp != NULL) { - if (gp->softc != NULL) - g_free(gp->softc); - g_destroy_geom(gp); - } - return (NULL); } static int @@ -348,8 +336,6 @@ g_multipath_add_disk(struct g_geom *gp, struct g_provider *pp) } nxtcp = LIST_FIRST(&gp->consumer); cp = g_new_consumer(gp); - if (cp == NULL) - return (ENOMEM); error = g_attach(cp, pp); if (error != 0) { printf("GEOM_MULTIPATH: cannot attach %s to %s", diff --git a/sys/geom/sched/g_sched.c b/sys/geom/sched/g_sched.c index 031d68d..dd5120f 100644 --- a/sys/geom/sched/g_sched.c +++ b/sys/geom/sched/g_sched.c @@ -1004,11 +1004,6 @@ g_sched_create(struct gctl_req *req, struct g_class *mp, gp = g_new_geomf(mp, name); dstgp = proxy ? pp->geom : gp; /* where do we link the provider */ - if (gp == NULL) { - gctl_error(req, "Cannot create geom %s.", name); - error = ENOMEM; - goto fail; - } sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); sc->sc_gsched = gsp; @@ -1034,23 +1029,10 @@ g_sched_create(struct gctl_req *req, struct g_class *mp, gp->dumpconf = g_sched_dumpconf; newpp = g_new_providerf(dstgp, gp->name); - if (newpp == NULL) { - gctl_error(req, "Cannot create provider %s.", name); - error = ENOMEM; - goto fail; - } - newpp->mediasize = pp->mediasize; newpp->sectorsize = pp->sectorsize; cp = g_new_consumer(gp); - if (cp == NULL) { - gctl_error(req, "Cannot create consumer for %s.", - gp->name); - error = ENOMEM; - goto fail; - } - error = g_attach(cp, proxy ? newpp : pp); if (error != 0) { gctl_error(req, "Cannot attach to provider %s.", @@ -1076,23 +1058,15 @@ fail: g_detach(cp); g_destroy_consumer(cp); } - if (newpp != NULL) g_destroy_provider(newpp); - - if (sc && sc->sc_hash) { + if (sc->sc_hash) g_sched_hash_fini(gp, sc->sc_hash, sc->sc_mask, gsp, sc->sc_data); - } - - if (sc && sc->sc_data) + if (sc->sc_data) gsp->gs_fini(sc->sc_data); - - if (gp != NULL) { - if (gp->softc != NULL) - g_free(gp->softc); - g_destroy_geom(gp); - } + g_free(gp->softc); + g_destroy_geom(gp); return (error); } diff --git a/sys/geom/shsec/g_shsec.c b/sys/geom/shsec/g_shsec.c index a2d9e12..4bf918f 100644 --- a/sys/geom/shsec/g_shsec.c +++ b/sys/geom/shsec/g_shsec.c @@ -546,8 +546,6 @@ g_shsec_create(struct g_class *mp, const struct g_shsec_metadata *md) } } gp = g_new_geomf(mp, "%s", md->md_name); - gp->softc = NULL; /* for a moment */ - sc = malloc(sizeof(*sc), M_SHSEC, M_WAITOK | M_ZERO); gp->start = g_shsec_start; gp->spoiled = g_shsec_orphan; diff --git a/sys/geom/stripe/g_stripe.c b/sys/geom/stripe/g_stripe.c index b8faffd..08841b5 100644 --- a/sys/geom/stripe/g_stripe.c +++ b/sys/geom/stripe/g_stripe.c @@ -819,8 +819,6 @@ g_stripe_create(struct g_class *mp, const struct g_stripe_metadata *md, } } gp = g_new_geomf(mp, "%s", md->md_name); - gp->softc = NULL; /* for a moment */ - sc = malloc(sizeof(*sc), M_STRIPE, M_WAITOK | M_ZERO); gp->start = g_stripe_start; gp->spoiled = g_stripe_orphan; diff --git a/sys/mips/conf/PB92 b/sys/mips/conf/PB92 index 92d7976..dba70d8 100644 --- a/sys/mips/conf/PB92 +++ b/sys/mips/conf/PB92 @@ -6,9 +6,13 @@ # ident PB92 +# XXX The default load address in the Uboot environment is 0x80010000 makeoptions KERNLOADADDR=0x80050000 options HZ=1000 +# The PB92 has 32mb of RAM; hard-code that +options AR71XX_REALMEM=32*1024*1024 + hints "PB92.hints" include "../atheros/std.ar71xx" @@ -21,20 +25,17 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking options INET6 -options NFSCLIENT #Network Filesystem Client +# options NFSCLIENT #Network Filesystem Client options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options ALQ -# options NFS_LEGACYRPC -#options NFS_DEBUG - # Debugging for use in -current -options DEADLKRES -options INVARIANTS -options INVARIANT_SUPPORT -options WITNESS -options WITNESS_SKIPSPIN +#options DEADLKRES +#options INVARIANTS +#options INVARIANT_SUPPORT +#options WITNESS +#options WITNESS_SKIPSPIN options FFS #Berkeley Fast Filesystem #options SOFTUPDATES #Enable FFS soft updates support #options UFS_ACL #Support for access control lists @@ -46,9 +47,13 @@ device geom_uzip options GEOM_UZIP options ROOTDEVNAME=\"ufs:/dev/md0.uzip\" +# PCI bus device pci device ar724x_pci +# NVRAM U-Boot Environment -> Kernel environment +device nvram2env + # Wireless NIC cards options IEEE80211_DEBUG options IEEE80211_SUPPORT_MESH @@ -75,23 +80,42 @@ device ath_rate_sample device mii device arge +# USB devices - PB92 has EHCI only + device usb options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order options USB_DEBUG options USB_HOST_ALIGN=32 device ehci +# Mass storage +device scbus +device umass +device da + +# Read MSDOS formatted disks +options GEOM_PART_BSD +options GEOM_PART_MBR +options MSDOSFS + +# GPIO Bus device gpio device gpioled +# SPI and flash device spibus device ar71xx_spi device mx25l +# The flash is statically partitioned; add in that +device geom_map + device ar71xx_wdog +# Serial device uart +# Network twiddling device loop device ether device md diff --git a/sys/mips/conf/PB92.hints b/sys/mips/conf/PB92.hints index 014e62f..846d57d 100644 --- a/sys/mips/conf/PB92.hints +++ b/sys/mips/conf/PB92.hints @@ -9,12 +9,6 @@ hint.uart.0.maddr=0x18020003 hint.uart.0.msize=0x18 hint.uart.0.irq=3 -# ohci -#hint.ohci.0.at="apb0" -#hint.ohci.0.maddr=0x1b000000 -#hint.ohci.0.msize=0x01000000 -#hint.ohci.0.irq=1 - #ehci - note the 0x100 offset for the AR913x/AR724x hint.ehci.0.at="nexus0" hint.ehci.0.maddr=0x1b000100 @@ -67,3 +61,53 @@ hint.mx25l.0.cs=0 # Watchdog hint.ar71xx_wdog.0.at="nexus0" + +# nvram mapping - XXX ? +hint.nvram.0.base=0x1f030000 +hint.nvram.0.maxsize=0x2000 +hint.nvram.0.flags=3 # 1 = No check, 2 = Format Generic +hint.nvram.1.base=0x1f032000 +hint.nvram.1.maxsize=0x4000 +hint.nvram.1.flags=3 # 1 = No check, 2 = Format Generic + +# GEOM_MAP +# +# From my PB92 environment: +# +# mtdparts=ar7240-nor0:256k(u-boot),64k(u-boot-env),2752k(rootfs),896k(uImage),64k(NVRAM),64k(ART) + +hint.map.0.at="flash/spi0" +hint.map.0.start=0x00000000 +hint.map.0.end=0x00040000 # 256k u-boot +hint.map.0.name="u-boot" +hint.map.0.readonly=1 + +hint.map.1.at="flash/spi0" +hint.map.1.start=0x00040000 +hint.map.1.end=0x00050000 # 64k u-boot-env +hint.map.1.name="u-boot-env" +hint.map.1.readonly=0 + +hint.map.2.at="flash/spi0" +hint.map.2.start=0x00050000 +hint.map.2.end=0x00300000 # 2752k rootfs +hint.map.2.name="rootfs" +hint.map.2.readonly=1 + +hint.map.3.at="flash/spi0" +hint.map.3.start=0x00300000 +hint.map.3.end=0x003e0000 # 896k uImage +hint.map.3.name="uImage" +hint.map.3.readonly=0 + +hint.map.4.at="flash/spi0" +hint.map.4.start=0x003e0000 +hint.map.4.end=0x003f0000 # 64k NVRAM +hint.map.4.name="NVRAM" +hint.map.4.readonly=0 + +hint.map.5.at="flash/spi0" +hint.map.5.start=0x003f0000 +hint.map.5.end=0x00400000 # 64k ART +hint.map.5.name="ART" +hint.map.5.readonly=1 diff --git a/sys/modules/cxgbe/if_cxgbe/Makefile b/sys/modules/cxgbe/if_cxgbe/Makefile index 5bfe646..a524cde 100644 --- a/sys/modules/cxgbe/if_cxgbe/Makefile +++ b/sys/modules/cxgbe/if_cxgbe/Makefile @@ -13,4 +13,7 @@ SRCS+= opt_inet.h CFLAGS+= -I${CXGBE} +# Provide the timestamp of a packet in its header mbuf. +#CFLAGS+= -DT4_PKT_TIMESTAMP + .include <bsd.kmod.mk> diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index 1e86415..fa29a75 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -265,6 +265,13 @@ struct sctp_paramhdr { #define SCTP_CC_OPT_USE_DCCC_ECN 0x00002001 #define SCTP_CC_OPT_STEADY_STEP 0x00002002 +#define SCTP_CMT_OFF 0 +#define SCTP_CMT_BASE 1 +#define SCTP_CMT_RPV1 2 +#define SCTP_CMT_RPV2 3 +#define SCTP_CMT_MPTCP 4 +#define SCTP_CMT_MAX SCTP_CMT_MPTCP + /* RS - Supported stream scheduling modules for pluggable * stream scheduling */ diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c index 3d52820..85beb6a 100644 --- a/sys/netinet/sctp_cc_functions.c +++ b/sys/netinet/sctp_cc_functions.c @@ -47,6 +47,10 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#define SHIFT_MPTCP_MULTI_N 40 +#define SHIFT_MPTCP_MULTI_Z 16 +#define SHIFT_MPTCP_MULTI 8 + static void sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net) { @@ -67,7 +71,8 @@ sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net) cwnd_in_mtu = assoc->max_burst; net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu; } - if (stcb->asoc.sctp_cmt_on_off == 2) { + if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) || + (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) { /* In case of resource pooling initialize appropriately */ net->cwnd /= assoc->numnets; if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) { @@ -91,14 +96,23 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, { struct sctp_nets *net; uint32_t t_ssthresh, t_cwnd; + uint64_t t_ucwnd_sbw; /* MT FIXME: Don't compute this over and over again */ t_ssthresh = 0; t_cwnd = 0; - if (asoc->sctp_cmt_on_off == 2) { + t_ucwnd_sbw = 0; + if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) || + (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) { TAILQ_FOREACH(net, &asoc->nets, sctp_next) { t_ssthresh += net->ssthresh; t_cwnd += net->cwnd; + if (net->lastsa > 0) { + t_ucwnd_sbw += (uint64_t) net->cwnd / (uint64_t) net->lastsa; + } + } + if (t_ucwnd_sbw == 0) { + t_ucwnd_sbw = 1; } } /*- @@ -119,11 +133,37 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, struct sctp_tmit_chunk *lchk; int old_cwnd = net->cwnd; - if (asoc->sctp_cmt_on_off == 2) { - net->ssthresh = (uint32_t) (((uint64_t) 4 * - (uint64_t) net->mtu * - (uint64_t) net->ssthresh) / - (uint64_t) t_ssthresh); + if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) || + (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) { + if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) { + net->ssthresh = (uint32_t) (((uint64_t) 4 * + (uint64_t) net->mtu * + (uint64_t) net->ssthresh) / + (uint64_t) t_ssthresh); + + } + if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) { + uint32_t srtt; + + srtt = net->lastsa; + /* + * lastsa>>3; we don't need + * to devide ... + */ + if (srtt == 0) { + srtt = 1; + } + /* + * Short Version => Equal to + * Contel Version MBe + */ + net->ssthresh = (uint32_t) (((uint64_t) 4 * + (uint64_t) net->mtu * + (uint64_t) net->cwnd) / + ((uint64_t) srtt * + t_ucwnd_sbw)); + /* INCREASE FACTOR */ ; + } if ((net->cwnd > t_cwnd / 2) && (net->ssthresh < net->cwnd - t_cwnd / 2)) { net->ssthresh = net->cwnd - t_cwnd / 2; @@ -629,14 +669,47 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, struct sctp_nets *net; int old_cwnd; uint32_t t_ssthresh, t_cwnd, incr; + uint64_t t_ucwnd_sbw; + uint64_t t_path_mptcp; + uint64_t mptcp_like_alpha; + uint32_t srtt; + uint64_t max_path; /* MT FIXME: Don't compute this over and over again */ t_ssthresh = 0; t_cwnd = 0; - if (stcb->asoc.sctp_cmt_on_off == 2) { + t_ucwnd_sbw = 0; + t_path_mptcp = 0; + mptcp_like_alpha = 1; + if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) || + (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) || + (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) { + max_path = 0; TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { t_ssthresh += net->ssthresh; t_cwnd += net->cwnd; + /* lastsa>>3; we don't need to devide ... */ + srtt = net->lastsa; + if (srtt > 0) { + uint64_t tmp; + + t_ucwnd_sbw += (uint64_t) net->cwnd / (uint64_t) srtt; + t_path_mptcp += (((uint64_t) net->cwnd) << SHIFT_MPTCP_MULTI_Z) / + (((uint64_t) net->mtu) * (uint64_t) srtt); + tmp = (((uint64_t) net->cwnd) << SHIFT_MPTCP_MULTI_N) / + ((uint64_t) net->mtu * (uint64_t) (srtt * srtt)); + if (tmp > max_path) { + max_path = tmp; + } + } + } + if (t_ucwnd_sbw == 0) { + t_ucwnd_sbw = 1; + } + if (t_path_mptcp > 0) { + mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp); + } else { + mptcp_like_alpha = 1; } } /******************************/ @@ -818,10 +891,11 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, if (net->cwnd <= net->ssthresh) { /* We are in slow start */ if (net->flight_size + net->net_ack >= net->cwnd) { - old_cwnd = net->cwnd; - if (stcb->asoc.sctp_cmt_on_off == 2) { - uint32_t limit; + uint32_t limit; + old_cwnd = net->cwnd; + switch (asoc->sctp_cmt_on_off) { + case SCTP_CMT_RPV1: limit = (uint32_t) (((uint64_t) net->mtu * (uint64_t) SCTP_BASE_SYSCTL(sctp_L2_abc_variable) * (uint64_t) net->ssthresh) / @@ -835,11 +909,56 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, if (incr == 0) { incr = 1; } - } else { + break; + case SCTP_CMT_RPV2: + /* + * lastsa>>3; we don't need + * to divide ... + */ + srtt = net->lastsa; + if (srtt == 0) { + srtt = 1; + } + limit = (uint32_t) (((uint64_t) net->mtu * + (uint64_t) SCTP_BASE_SYSCTL(sctp_L2_abc_variable) * + (uint64_t) net->cwnd) / + ((uint64_t) srtt * t_ucwnd_sbw)); + /* INCREASE FACTOR */ + incr = (uint32_t) (((uint64_t) net->net_ack * + (uint64_t) net->cwnd) / + ((uint64_t) srtt * t_ucwnd_sbw)); + /* INCREASE FACTOR */ + if (incr > limit) { + incr = limit; + } + if (incr == 0) { + incr = 1; + } + break; + case SCTP_CMT_MPTCP: + limit = (uint32_t) (((uint64_t) net->mtu * + mptcp_like_alpha * + (uint64_t) SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >> + SHIFT_MPTCP_MULTI); + incr = (uint32_t) (((uint64_t) net->net_ack * + mptcp_like_alpha) >> + SHIFT_MPTCP_MULTI); + if (incr > limit) { + incr = limit; + } + if (incr > net->net_ack) { + incr = net->net_ack; + } + if (incr > net->mtu) { + incr = net->mtu; + } + break; + default: incr = net->net_ack; if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) { incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable); } + break; } net->cwnd += incr; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { @@ -868,15 +987,44 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, (net->partial_bytes_acked >= net->cwnd)) { net->partial_bytes_acked -= net->cwnd; old_cwnd = net->cwnd; - if (asoc->sctp_cmt_on_off == 2) { + switch (asoc->sctp_cmt_on_off) { + case SCTP_CMT_RPV1: incr = (uint32_t) (((uint64_t) net->mtu * (uint64_t) net->ssthresh) / (uint64_t) t_ssthresh); if (incr == 0) { incr = 1; } - } else { + break; + case SCTP_CMT_RPV2: + /* + * lastsa>>3; we don't need + * to divide ... + */ + srtt = net->lastsa; + if (srtt == 0) { + srtt = 1; + } + incr = (uint32_t) ((uint64_t) net->mtu * + (uint64_t) net->cwnd / + ((uint64_t) srtt * + t_ucwnd_sbw)); + /* INCREASE FACTOR */ + if (incr == 0) { + incr = 1; + } + break; + case SCTP_CMT_MPTCP: + incr = (uint32_t) ((mptcp_like_alpha * + (uint64_t) net->cwnd) >> + SHIFT_MPTCP_MULTI); + if (incr > net->mtu) { + incr = net->mtu; + } + break; + default: incr = net->mtu; + break; } net->cwnd += incr; SDT_PROBE(sctp, cwnd, net, ack, @@ -926,21 +1074,49 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net) { int old_cwnd = net->cwnd; uint32_t t_ssthresh, t_cwnd; + uint64_t t_ucwnd_sbw; /* MT FIXME: Don't compute this over and over again */ t_ssthresh = 0; t_cwnd = 0; - if (stcb->asoc.sctp_cmt_on_off == 2) { + if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) || + (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) { struct sctp_nets *lnet; + uint32_t srtt; + t_ucwnd_sbw = 0; TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { t_ssthresh += lnet->ssthresh; t_cwnd += lnet->cwnd; + srtt = lnet->lastsa; + /* lastsa>>3; we don't need to divide ... */ + if (srtt > 0) { + t_ucwnd_sbw += (uint64_t) lnet->cwnd / (uint64_t) srtt; + } + } + if (t_ucwnd_sbw < 1) { + t_ucwnd_sbw = 1; + } + if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) { + net->ssthresh = (uint32_t) (((uint64_t) 4 * + (uint64_t) net->mtu * + (uint64_t) net->ssthresh) / + (uint64_t) t_ssthresh); + } else { + uint64_t cc_delta; + + srtt = net->lastsa; + /* lastsa>>3; we don't need to divide ... */ + if (srtt == 0) { + srtt = 1; + } + cc_delta = t_ucwnd_sbw * (uint64_t) srtt / 2; + if (cc_delta < t_cwnd) { + net->ssthresh = (uint32_t) ((uint64_t) t_cwnd - cc_delta); + } else { + net->ssthresh = net->mtu; + } } - net->ssthresh = (uint32_t) (((uint64_t) 4 * - (uint64_t) net->mtu * - (uint64_t) net->ssthresh) / - (uint64_t) t_ssthresh); if ((net->cwnd > t_cwnd / 2) && (net->ssthresh < net->cwnd - t_cwnd / 2)) { net->ssthresh = net->cwnd - t_cwnd / 2; diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h index 842d9b1..6429d59 100644 --- a/sys/netinet/sctp_sysctl.h +++ b/sys/netinet/sctp_sysctl.h @@ -336,9 +336,9 @@ struct sctp_sysctl { /* cmt_on_off: CMT on/off flag */ #define SCTPCTL_CMT_ON_OFF_DESC "CMT settings" -#define SCTPCTL_CMT_ON_OFF_MIN 0 -#define SCTPCTL_CMT_ON_OFF_MAX 2 -#define SCTPCTL_CMT_ON_OFF_DEFAULT 0 +#define SCTPCTL_CMT_ON_OFF_MIN SCTP_CMT_OFF +#define SCTPCTL_CMT_ON_OFF_MAX SCTP_CMT_MAX +#define SCTPCTL_CMT_ON_OFF_DEFAULT SCTP_CMT_OFF /* EY - nr_sack_on_off: NR_SACK on/off flag */ #define SCTPCTL_NR_SACK_ON_OFF_DESC "NR_SACK on/off flag" diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index cecfde7..734d92b 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -2992,18 +2992,22 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { - stcb->asoc.sctp_cmt_on_off = av->assoc_value; - if (stcb->asoc.sctp_cmt_on_off > 2) { - stcb->asoc.sctp_cmt_on_off = 2; + if (av->assoc_value > SCTP_CMT_MAX) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } else { + stcb->asoc.sctp_cmt_on_off = av->assoc_value; } SCTP_TCB_UNLOCK(stcb); } else { - SCTP_INP_WLOCK(inp); - inp->sctp_cmt_on_off = av->assoc_value; - if (inp->sctp_cmt_on_off > 2) { - inp->sctp_cmt_on_off = 2; + if (av->assoc_value > SCTP_CMT_MAX) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } else { + SCTP_INP_WLOCK(inp); + inp->sctp_cmt_on_off = av->assoc_value; + SCTP_INP_WUNLOCK(inp); } - SCTP_INP_WUNLOCK(inp); } } else { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); diff --git a/sys/nfs/nfs_nfssvc.c b/sys/nfs/nfs_nfssvc.c index cb1f37a..4296349 100644 --- a/sys/nfs/nfs_nfssvc.c +++ b/sys/nfs/nfs_nfssvc.c @@ -81,9 +81,12 @@ nfssvc(struct thread *td, struct nfssvc_args *uap) AUDIT_ARG_CMD(uap->flag); - error = priv_check(td, PRIV_NFS_DAEMON); - if (error) - return (error); + /* Allow anyone to get the stats. */ + if ((uap->flag & ~NFSSVC_GETSTATS) != 0) { + error = priv_check(td, PRIV_NFS_DAEMON); + if (error != 0) + return (error); + } error = EINVAL; if ((uap->flag & (NFSSVC_ADDSOCK | NFSSVC_OLDNFSD | NFSSVC_NFSD)) && nfsd_call_nfsserver != NULL) diff --git a/sys/sys/stddef.h b/sys/sys/stddef.h index 8e7f206..1581744 100644 --- a/sys/sys/stddef.h +++ b/sys/sys/stddef.h @@ -33,7 +33,10 @@ #include <sys/_null.h> #include <machine/_types.h> +#ifndef _PTRDIFF_T_DECLARED typedef __ptrdiff_t ptrdiff_t; +#define _PTRDIFF_T_DECLARED +#endif #define offsetof(type, field) __offsetof(type, field) |