summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2011-05-05 14:05:29 +0000
committerattilio <attilio@FreeBSD.org>2011-05-05 14:05:29 +0000
commitd3d3db9bac709a7fa4319bf5e8c8fb4e05918772 (patch)
tree1f3fc48f78abc0f826bc204651c01b9f8bbaed60 /sys
parentf756d5bed6346f4902b1da276e52098882a7a66b (diff)
parent1e6b02c145b56555ee32db7471bf964bde2eade9 (diff)
downloadFreeBSD-src-d3d3db9bac709a7fa4319bf5e8c8fb4e05918772.zip
FreeBSD-src-d3d3db9bac709a7fa4319bf5e8c8fb4e05918772.tar.gz
MFC
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar2133.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal.c16
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_reset.c26
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416reg.h53
-rw-r--r--sys/dev/bge/if_bge.c65
-rw-r--r--sys/dev/bge/if_bgereg.h14
-rw-r--r--sys/dev/cxgbe/offload.h2
-rw-r--r--sys/dev/cxgbe/t4_ioctl.h134
-rw-r--r--sys/dev/cxgbe/t4_main.c533
-rw-r--r--sys/dev/cxgbe/t4_sge.c43
-rw-r--r--sys/dev/mii/brgphy.c2
-rw-r--r--sys/fs/nfs/nfsproto.h8
-rw-r--r--sys/fs/nfsclient/nfs_clport.c34
-rw-r--r--sys/geom/cache/g_cache.c37
-rw-r--r--sys/geom/concat/g_concat.c2
-rw-r--r--sys/geom/eli/g_eli.c2
-rw-r--r--sys/geom/journal/g_journal.c1
-rw-r--r--sys/geom/mountver/g_mountver.c35
-rw-r--r--sys/geom/multipath/g_multipath.c14
-rw-r--r--sys/geom/sched/g_sched.c34
-rw-r--r--sys/geom/shsec/g_shsec.c2
-rw-r--r--sys/geom/stripe/g_stripe.c2
-rw-r--r--sys/mips/conf/PB9242
-rw-r--r--sys/mips/conf/PB92.hints56
-rw-r--r--sys/modules/cxgbe/if_cxgbe/Makefile3
-rw-r--r--sys/netinet/sctp.h7
-rw-r--r--sys/netinet/sctp_cc_functions.c214
-rw-r--r--sys/netinet/sctp_sysctl.h6
-rw-r--r--sys/netinet/sctp_usrreq.c20
-rw-r--r--sys/nfs/nfs_nfssvc.c9
-rw-r--r--sys/sys/stddef.h3
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)
OpenPOWER on IntegriCloud