diff options
author | jkim <jkim@FreeBSD.org> | 2009-06-04 21:31:03 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2009-06-04 21:31:03 +0000 |
commit | c643f667af35e7f3289792a8887ace2ef3392cd1 (patch) | |
tree | e7063b5e028be9e7caf684c14fc01c6625288e1e /sys | |
parent | c0abc08c0c3d602d6ca3b0d4f7870bed26e0529e (diff) | |
download | FreeBSD-src-c643f667af35e7f3289792a8887ace2ef3392cd1.zip FreeBSD-src-c643f667af35e7f3289792a8887ace2ef3392cd1.tar.gz |
Resync with head.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_zyd.c | 325 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_zydreg.h | 117 | ||||
-rw-r--r-- | sys/fs/devfs/devfs_vfsops.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 22 | ||||
-rw-r--r-- | sys/modules/usb/zyd/Makefile | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211.h | 10 | ||||
-rw-r--r-- | sys/net80211/ieee80211_hostap.c | 52 | ||||
-rw-r--r-- | sys/net80211/ieee80211_input.c | 12 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.c | 8 | ||||
-rw-r--r-- | sys/net80211/ieee80211_output.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 37 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.h | 1 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan.h | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_sta.c | 152 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_dummynet.h | 6 | ||||
-rw-r--r-- | sys/nlm/nlm_advlock.c | 4 | ||||
-rw-r--r-- | sys/rpc/clnt_dg.c | 27 | ||||
-rw-r--r-- | sys/rpc/clnt_vc.c | 29 | ||||
-rw-r--r-- | sys/rpc/svc.c | 9 | ||||
-rw-r--r-- | sys/rpc/svc.h | 1 | ||||
-rw-r--r-- | sys/rpc/svc_vc.c | 17 | ||||
-rw-r--r-- | sys/sys/mount.h | 1 |
24 files changed, 599 insertions, 245 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index 831bd2d..a2bf460 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -573,6 +573,7 @@ zfs_domount(vfs_t *vfsp, char *osname) vfsp->mnt_flag |= MNT_LOCAL; vfsp->mnt_kern_flag |= MNTK_MPSAFE; vfsp->mnt_kern_flag |= MNTK_LOOKUP_SHARED; + vfsp->mnt_kern_flag |= MNTK_SHARED_WRITES; if (error = dsl_prop_get_integer(osname, "readonly", &readonly, NULL)) goto out; diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index 3e98263..6307309 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -190,9 +190,10 @@ static int zyd_al2210_set_channel(struct zyd_rf *, uint8_t); static int zyd_gct_init(struct zyd_rf *); static int zyd_gct_switch_radio(struct zyd_rf *, int); static int zyd_gct_set_channel(struct zyd_rf *, uint8_t); -static int zyd_maxim_init(struct zyd_rf *); -static int zyd_maxim_switch_radio(struct zyd_rf *, int); -static int zyd_maxim_set_channel(struct zyd_rf *, uint8_t); +static int zyd_gct_mode(struct zyd_rf *); +static int zyd_gct_set_channel_synth(struct zyd_rf *, int, int); +static int zyd_gct_write(struct zyd_rf *, uint16_t); +static int zyd_gct_txgain(struct zyd_rf *, uint8_t); static int zyd_maxim2_init(struct zyd_rf *); static int zyd_maxim2_switch_radio(struct zyd_rf *, int); static int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t); @@ -204,55 +205,59 @@ static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB; #define ZYD_ZD1211 0 #define ZYD_ZD1211B 1 +#define ZYD_ZD1211_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, ZYD_ZD1211) } +#define ZYD_ZD1211B_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, ZYD_ZD1211B) } static const struct usb_device_id zyd_devs[] = { - /* ZYD_ZD1211 */ - {USB_VPI(USB_VENDOR_3COM2, USB_PRODUCT_3COM2_3CRUSB10075, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WL54, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL159G, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_CYBERTAN, USB_PRODUCT_CYBERTAN_TG54USB, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_DRAYTEK, USB_PRODUCT_DRAYTEK_VIGOR550, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GD, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GZL, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54GZ, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54MINI, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG760A, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_SENAO, USB_PRODUCT_SENAO_NUB8301, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_SWEEX, USB_PRODUCT_SWEEX_ZD1211, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_QUICKWLAN, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_1, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_2, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_G240, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_ALL0298V2, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB_A, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR055G, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_AG225H, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_ZYAIRG220, ZYD_ZD1211)}, - {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G200V2, ZYD_ZD1211)}, - /* ZYD_ZD1211B */ - {USB_VPI(USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBG, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_ZD1211B, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_A9T_WIFI, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050_V4000, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_ZD1211B, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSBF54G, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_FIBERLINE, USB_PRODUCT_FIBERLINE_WL430U, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54L, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SNU5600, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US54GXS, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG76NA, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_ZD1211B, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UBC1, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_USR, USB_PRODUCT_USR_USR5423, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_VTECH, USB_PRODUCT_VTECH_ZD1211B, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211B, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211B, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_M202, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G202, ZYD_ZD1211B)}, - {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G220V2, ZYD_ZD1211B)}, + /* ZYD_ZD1211 */ + ZYD_ZD1211_DEV(3COM2, 3CRUSB10075), + ZYD_ZD1211_DEV(ABOCOM, WL54), + ZYD_ZD1211_DEV(ASUS, WL159G), + ZYD_ZD1211_DEV(CYBERTAN, TG54USB), + ZYD_ZD1211_DEV(DRAYTEK, VIGOR550), + ZYD_ZD1211_DEV(PLANEX2, GWUS54GD), + ZYD_ZD1211_DEV(PLANEX2, GWUS54GZL), + ZYD_ZD1211_DEV(PLANEX3, GWUS54GZ), + ZYD_ZD1211_DEV(PLANEX3, GWUS54MINI), + ZYD_ZD1211_DEV(SAGEM, XG760A), + ZYD_ZD1211_DEV(SENAO, NUB8301), + ZYD_ZD1211_DEV(SITECOMEU, WL113), + ZYD_ZD1211_DEV(SWEEX, ZD1211), + ZYD_ZD1211_DEV(TEKRAM, QUICKWLAN), + ZYD_ZD1211_DEV(TEKRAM, ZD1211_1), + ZYD_ZD1211_DEV(TEKRAM, ZD1211_2), + ZYD_ZD1211_DEV(TWINMOS, G240), + ZYD_ZD1211_DEV(UMEDIA, ALL0298V2), + ZYD_ZD1211_DEV(UMEDIA, TEW429UB_A), + ZYD_ZD1211_DEV(UMEDIA, TEW429UB), + ZYD_ZD1211_DEV(WISTRONNEWEB, UR055G), + ZYD_ZD1211_DEV(ZCOM, ZD1211), + ZYD_ZD1211_DEV(ZYDAS, ZD1211), + ZYD_ZD1211_DEV(ZYXEL, AG225H), + ZYD_ZD1211_DEV(ZYXEL, ZYAIRG220), + ZYD_ZD1211_DEV(ZYXEL, G200V2), + /* ZYD_ZD1211B */ + ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG), + ZYD_ZD1211B_DEV(ACCTON, ZD1211B), + ZYD_ZD1211B_DEV(ASUS, A9T_WIFI), + ZYD_ZD1211B_DEV(BELKIN, F5D7050_V4000), + ZYD_ZD1211B_DEV(BELKIN, ZD1211B), + ZYD_ZD1211B_DEV(CISCOLINKSYS, WUSBF54G), + ZYD_ZD1211B_DEV(FIBERLINE, WL430U), + ZYD_ZD1211B_DEV(MELCO, KG54L), + ZYD_ZD1211B_DEV(PHILIPS, SNU5600), + ZYD_ZD1211B_DEV(PLANEX2, GW_US54GXS), + ZYD_ZD1211B_DEV(SAGEM, XG76NA), + ZYD_ZD1211B_DEV(SITECOMEU, ZD1211B), + ZYD_ZD1211B_DEV(UMEDIA, TEW429UBC1), + ZYD_ZD1211B_DEV(USR, USR5423), + ZYD_ZD1211B_DEV(VTECH, ZD1211B), + ZYD_ZD1211B_DEV(ZCOM, ZD1211B), + ZYD_ZD1211B_DEV(ZYDAS, ZD1211B), + ZYD_ZD1211B_DEV(ZYXEL, M202), + ZYD_ZD1211B_DEV(ZYXEL, G202), + ZYD_ZD1211B_DEV(ZYXEL, G220V2) }; static const struct usb_config zyd_config[ZYD_N_TRANSFER] = { @@ -1417,11 +1422,14 @@ fail: static int zyd_gct_init(struct zyd_rf *rf) { +#define ZYD_GCT_INTR_REG 0x85c1 #define N(a) (sizeof(a) / sizeof((a)[0])) struct zyd_softc *sc = rf->rf_sc; static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY; static const uint32_t rfini[] = ZYD_GCT_RF; - int i, error; + static const uint16_t vco[11][7] = ZYD_GCT_VCO; + int i, idx = -1, error; + uint16_t data; /* init RF-dependent PHY registers */ for (i = 0; i < N(phyini); i++) @@ -1432,122 +1440,153 @@ zyd_gct_init(struct zyd_rf *rf) if ((error = zyd_rfwrite(sc, rfini[i])) != 0) return (error); } + + error = zyd_gct_mode(rf); + if (error != 0) + return (error); + + for (i = 0; i < N(vco) - 1; i++) { + error = zyd_gct_set_channel_synth(rf, 1, 0); + if (error != 0) + goto fail; + error = zyd_gct_write(rf, vco[i][0]); + if (error != 0) + goto fail; + zyd_write16_m(sc, ZYD_GCT_INTR_REG, 0xf); + zyd_read16_m(sc, ZYD_GCT_INTR_REG, &data); + if ((data & 0xf) == 0) { + idx = i; + break; + } + } + if (idx == -1) { + error = zyd_gct_set_channel_synth(rf, 1, 1); + if (error != 0) + goto fail; + error = zyd_gct_write(rf, 0x6662); + if (error != 0) + goto fail; + } + + rf->idx = idx; + zyd_write16_m(sc, ZYD_CR203, 0x6); fail: return (error); #undef N +#undef ZYD_GCT_INTR_REG } static int -zyd_gct_switch_radio(struct zyd_rf *rf, int on) +zyd_gct_mode(struct zyd_rf *rf) { - /* vendor driver does nothing for this RF chip */ +#define N(a) (sizeof(a) / sizeof((a)[0])) + struct zyd_softc *sc = rf->rf_sc; + static const uint32_t mode[] = { + 0x25f98, 0x25f9a, 0x25f94, 0x27fd4 + }; + int i, error; - return (0); + for (i = 0; i < N(mode); i++) { + if ((error = zyd_rfwrite(sc, mode[i])) != 0) + break; + } + return (error); +#undef N } static int -zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan) +zyd_gct_set_channel_synth(struct zyd_rf *rf, int chan, int acal) { - int error; + int error, idx = chan - 1; struct zyd_softc *sc = rf->rf_sc; - static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE; + static uint32_t acal_synth[] = ZYD_GCT_CHANNEL_ACAL; + static uint32_t std_synth[] = ZYD_GCT_CHANNEL_STD; + static uint32_t div_synth[] = ZYD_GCT_CHANNEL_DIV; - error = zyd_rfwrite(sc, 0x1c0000); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1]); + error = zyd_rfwrite(sc, + (acal == 1) ? acal_synth[idx] : std_synth[idx]); if (error != 0) - goto fail; - error = zyd_rfwrite(sc, 0x1c0008); -fail: - return (error); + return (error); + return zyd_rfwrite(sc, div_synth[idx]); } -/* - * Maxim RF methods. - */ static int -zyd_maxim_init(struct zyd_rf *rf) +zyd_gct_write(struct zyd_rf *rf, uint16_t value) { -#define N(a) (sizeof(a) / sizeof((a)[0])) struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; - static const uint32_t rfini[] = ZYD_MAXIM_RF; - uint16_t tmp; - int i, error; - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* init maxim radio */ - for (i = 0; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -#undef N + return zyd_rfwrite(sc, 0x300000 | 0x40000 | value); } static int -zyd_maxim_switch_radio(struct zyd_rf *rf, int on) +zyd_gct_switch_radio(struct zyd_rf *rf, int on) { +#define N(a) (sizeof(a) / sizeof((a)[0])) + int error; + struct zyd_softc *sc = rf->rf_sc; - /* vendor driver does nothing for this RF chip */ - return (0); + error = zyd_rfwrite(sc, on ? 0x25f94 : 0x25f90); + if (error != 0) + return (error); + + zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); + zyd_write16_m(sc, ZYD_CR251, + on ? ((sc->sc_macrev == ZYD_ZD1211B) ? 0x7f : 0x3f) : 0x2f); +fail: + return (error); } static int -zyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan) +zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan) { #define N(a) (sizeof(a) / sizeof((a)[0])) + int error, i; struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; - static const uint32_t rfini[] = ZYD_MAXIM_RF; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_MAXIM_CHANTABLE; - uint16_t tmp; - int i, error; - - /* - * Do the same as we do when initializing it, except for the channel - * values coming from the two channel tables. - */ - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); + static const struct zyd_phy_pair cmd[] = { + { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR79, 0x58 }, + { ZYD_CR12, 0xf0 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x58 }, + }; + static const uint16_t vco[11][7] = ZYD_GCT_VCO; - /* first two values taken from the chantables */ - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); + error = zyd_gct_set_channel_synth(rf, chan, 0); if (error != 0) goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); + error = zyd_gct_write(rf, (rf->idx == -1) ? 0x6662 : + vco[rf->idx][((chan - 1) / 2)]); if (error != 0) goto fail; - - /* init maxim radio - skipping the two first values */ - for (i = 2; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); + error = zyd_gct_mode(rf); + if (error != 0) + return (error); + for (i = 0; i < N(cmd); i++) + zyd_write16_m(sc, cmd[i].reg, cmd[i].val); + error = zyd_gct_txgain(rf, chan); + if (error != 0) + return (error); + zyd_write16_m(sc, ZYD_CR203, 0x6); fail: return (error); #undef N } +static int +zyd_gct_txgain(struct zyd_rf *rf, uint8_t chan) +{ +#define N(a) (sizeof(a) / sizeof((a)[0])) + struct zyd_softc *sc = rf->rf_sc; + static uint32_t txgain[] = ZYD_GCT_TXGAIN; + uint8_t idx = sc->sc_pwrint[chan - 1]; + + if (idx >= N(txgain)) { + device_printf(sc->sc_dev, "could not set TX gain (%d %#x)\n", + chan, idx); + return 0; + } + + return zyd_rfwrite(sc, 0x700000 | txgain[idx]); +#undef N +} + /* * Maxim2 RF methods. */ @@ -1639,6 +1678,7 @@ zyd_rf_attach(struct zyd_softc *sc, uint8_t type) struct zyd_rf *rf = &sc->sc_rf; rf->rf_sc = sc; + rf->update_pwr = 1; switch (type) { case ZYD_RF_RFMD: @@ -1672,17 +1712,13 @@ zyd_rf_attach(struct zyd_softc *sc, uint8_t type) rf->set_channel = zyd_al2210_set_channel; rf->width = 24; /* 24-bit RF values */ break; + case ZYD_RF_MAXIM_NEW: case ZYD_RF_GCT: rf->init = zyd_gct_init; rf->switch_radio = zyd_gct_switch_radio; rf->set_channel = zyd_gct_set_channel; - rf->width = 21; /* 21-bit RF values */ - break; - case ZYD_RF_MAXIM_NEW: - rf->init = zyd_maxim_init; - rf->switch_radio = zyd_maxim_switch_radio; - rf->set_channel = zyd_maxim_set_channel; - rf->width = 18; /* 18-bit RF values */ + rf->width = 24; /* 24-bit RF values */ + rf->update_pwr = 0; break; case ZYD_RF_MAXIM_NEW2: rf->init = zyd_maxim2_init; @@ -2062,16 +2098,21 @@ zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c) if (error != 0) goto fail; - /* update Tx power */ - zyd_write16_m(sc, ZYD_CR31, sc->sc_pwrint[chan - 1]); + if (rf->update_pwr) { + /* update Tx power */ + zyd_write16_m(sc, ZYD_CR31, sc->sc_pwrint[chan - 1]); - if (sc->sc_macrev == ZYD_ZD1211B) { - zyd_write16_m(sc, ZYD_CR67, sc->sc_ofdm36_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR66, sc->sc_ofdm48_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR65, sc->sc_ofdm54_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR68, sc->sc_pwrcal[chan - 1]); - zyd_write16_m(sc, ZYD_CR69, 0x28); - zyd_write16_m(sc, ZYD_CR69, 0x2a); + if (sc->sc_macrev == ZYD_ZD1211B) { + zyd_write16_m(sc, ZYD_CR67, + sc->sc_ofdm36_cal[chan - 1]); + zyd_write16_m(sc, ZYD_CR66, + sc->sc_ofdm48_cal[chan - 1]); + zyd_write16_m(sc, ZYD_CR65, + sc->sc_ofdm54_cal[chan - 1]); + zyd_write16_m(sc, ZYD_CR68, sc->sc_pwrcal[chan - 1]); + zyd_write16_m(sc, ZYD_CR69, 0x28); + zyd_write16_m(sc, ZYD_CR69, 0x2a); + } } if (sc->sc_cckgain) { /* set CCK baseband gain from EEPROM */ diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h index 3b98398..0956dc0 100644 --- a/sys/dev/usb/wlan/if_zydreg.h +++ b/sys/dev/usb/wlan/if_zydreg.h @@ -840,82 +840,75 @@ #define ZYD_GCT_PHY \ { \ - { ZYD_CR47, 0x1e }, { ZYD_CR15, 0xdc }, { ZYD_CR113, 0xc0 }, \ - { ZYD_CR20, 0x0c }, { ZYD_CR17, 0x65 }, { ZYD_CR34, 0x04 }, \ - { ZYD_CR35, 0x35 }, { ZYD_CR24, 0x20 }, { ZYD_CR9, 0xe0 }, \ - { ZYD_CR127, 0x02 }, { ZYD_CR10, 0x91 }, { ZYD_CR23, 0x7f }, \ - { ZYD_CR27, 0x10 }, { ZYD_CR28, 0x7a }, { ZYD_CR79, 0xb5 }, \ - { ZYD_CR64, 0x80 }, { ZYD_CR33, 0x28 }, { ZYD_CR38, 0x30 } \ + { ZYD_CR10, 0x89 }, { ZYD_CR15, 0x20 }, { ZYD_CR17, 0x28 }, \ + { ZYD_CR23, 0x38 }, { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x93 }, \ + { ZYD_CR27, 0x15 }, { ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, \ + { ZYD_CR33, 0x28 }, { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x43 }, \ + { ZYD_CR41, 0x24 }, { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x92 }, \ + { ZYD_CR47, 0x1e }, { ZYD_CR48, 0x04 }, { ZYD_CR49, 0xfa }, \ + { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, \ + { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, { ZYD_CR91, 0x00 }, \ + { ZYD_CR92, 0x0a }, { ZYD_CR98, 0x8d }, { ZYD_CR99, 0x28 }, \ + { ZYD_CR100, 0x02 }, { ZYD_CR101, 0x09 }, { ZYD_CR102, 0x27 }, \ + { ZYD_CR106, 0x1c }, { ZYD_CR107, 0x1c }, { ZYD_CR109, 0x13 }, \ + { ZYD_CR110, 0x1f }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x1f }, \ + { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x23 }, { ZYD_CR115, 0x24 }, \ + { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xf0 }, \ + { ZYD_CR119, 0x1a }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x1f }, \ + { ZYD_CR122, 0xf0 }, { ZYD_CR123, 0x57 }, { ZYD_CR125, 0xad }, \ + { ZYD_CR126, 0x6c }, { ZYD_CR127, 0x03 }, { ZYD_CR128, 0x14 }, \ + { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR137, 0x50 }, \ + { ZYD_CR138, 0xa8 }, { ZYD_CR144, 0xac }, { ZYD_CR146, 0x20 }, \ + { ZYD_CR252, 0xff }, { ZYD_CR253, 0xff } \ } #define ZYD_GCT_RF \ { \ - 0x1f0000, 0x1f0000, 0x1f0200, 0x1f0600, 0x1f8600, 0x1f8600, \ - 0x002050, 0x1f8000, 0x1f8200, 0x1f8600, 0x1c0000, 0x10c458, \ - 0x088e92, 0x187b82, 0x0401b4, 0x140816, 0x0c7000, 0x1c0000, \ - 0x02ccae, 0x128023, 0x0a0000, 0x1a0000, 0x06e380, 0x16cb94, \ - 0x0e1740, 0x014980, 0x116240, 0x090000, 0x192304, 0x05112f, \ - 0x0d54a8, 0x0f8000, 0x1c0008, 0x1c0000, 0x1a0000, 0x1c0008, \ - 0x150000, 0x0c7000, 0x150800, 0x150000 \ + 0x40002b, 0x519e4f, 0x6f81ad, 0x73fffe, 0x25f9c, 0x100047, \ + 0x200999, 0x307602, 0x346063, \ } -#define ZYD_GCT_CHANTABLE \ +#define ZYD_GCT_VCO \ { \ - 0x1a0000, 0x1a8000, 0x1a4000, 0x1ac000, 0x1a2000, 0x1aa000, \ - 0x1a6000, 0x1ae000, 0x1a1000, 0x1a9000, 0x1a5000, 0x1ad000, \ - 0x1a3000, 0x1ab000 \ + { 0x664d, 0x604d, 0x6675, 0x6475, 0x6655, 0x6455, 0x6665 }, \ + { 0x666d, 0x606d, 0x664d, 0x644d, 0x6675, 0x6475, 0x6655 }, \ + { 0x665d, 0x605d, 0x666d, 0x646d, 0x664d, 0x644d, 0x6675 }, \ + { 0x667d, 0x607d, 0x665d, 0x645d, 0x666d, 0x646d, 0x664d }, \ + { 0x6643, 0x6043, 0x667d, 0x647d, 0x665d, 0x645d, 0x666d }, \ + { 0x6663, 0x6063, 0x6643, 0x6443, 0x667d, 0x647d, 0x665d }, \ + { 0x6653, 0x6053, 0x6663, 0x6463, 0x6643, 0x6443, 0x667d }, \ + { 0x6673, 0x6073, 0x6653, 0x6453, 0x6663, 0x6463, 0x6643 }, \ + { 0x664b, 0x604b, 0x6673, 0x6473, 0x6653, 0x6453, 0x6663 }, \ + { 0x666b, 0x606b, 0x664b, 0x644b, 0x6673, 0x6473, 0x6653 }, \ + { 0x665b, 0x605b, 0x666b, 0x646b, 0x664b, 0x644b, 0x6673 } \ } -#define ZYD_MAXIM_PHY \ +#define ZYD_GCT_TXGAIN \ { \ - { ZYD_CR23, 0x40 }, { ZYD_CR15, 0x20 }, { ZYD_CR28, 0x3e }, \ - { ZYD_CR29, 0x00 }, { ZYD_CR26, 0x11 }, { ZYD_CR44, 0x33 }, \ - { ZYD_CR106, 0x2a }, { ZYD_CR107, 0x1a }, { ZYD_CR109, 0x2b }, \ - { ZYD_CR110, 0x2b }, { ZYD_CR111, 0x2b }, { ZYD_CR112, 0x2b }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0xfa }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, { ZYD_CR122, 0xfe }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x27 }, { ZYD_CR111, 0x27 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0x00 }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x06 }, { ZYD_CR122, 0xfe }, \ - { ZYD_CR150, 0x0d } \ + 0x0e313, 0x0fb13, 0x0e093, 0x0f893, 0x0ea93, 0x1f093, 0x1f493, \ + 0x1f693, 0x1f393, 0x1f35b, 0x1e6db, 0x1ff3f, 0x1ffff, 0x361d7, \ + 0x37fbf, 0x3ff8b, 0x3ff33, 0x3fb3f, 0x3ffff \ } -#define ZYD_MAXIM_RF \ +#define ZYD_GCT_CHANNEL_ACAL \ { \ - 0x00ccd4, 0x030a03, 0x000400, 0x000ca1, 0x010072, 0x018645, \ - 0x004006, 0x0000a7, 0x008258, 0x003fc9, 0x00040a, 0x00000b, \ - 0x00026c \ + 0x106847, 0x106847, 0x106867, 0x106867, 0x106867, 0x106867, \ + 0x106857, 0x106857, 0x106857, 0x106857, 0x106877, 0x106877, \ + 0x106877, 0x10684f \ } -#define ZYD_MAXIM_CHANTABLE \ -{ \ - { 0x0ccd4, 0x30a03 }, \ - { 0x22224, 0x00a13 }, \ - { 0x37774, 0x10a13 }, \ - { 0x0ccd4, 0x30a13 }, \ - { 0x22224, 0x00a23 }, \ - { 0x37774, 0x10a23 }, \ - { 0x0ccd4, 0x30a23 }, \ - { 0x22224, 0x00a33 }, \ - { 0x37774, 0x10a33 }, \ - { 0x0ccd4, 0x30a33 }, \ - { 0x22224, 0x00a43 }, \ - { 0x37774, 0x10a43 }, \ - { 0x0ccd4, 0x30a43 }, \ - { 0x199a4, 0x20a53 } \ +#define ZYD_GCT_CHANNEL_STD \ +{ \ + 0x100047, 0x100047, 0x100067, 0x100067, 0x100067, 0x100067, \ + 0x100057, 0x100057, 0x100057, 0x100057, 0x100077, 0x100077, \ + 0x100077, 0x10004f \ +} + +#define ZYD_GCT_CHANNEL_DIV \ +{ \ + 0x200999, 0x20099b, 0x200998, 0x20099a, 0x200999, 0x20099b, \ + 0x200998, 0x20099a, 0x200999, 0x20099b, 0x200998, 0x20099a, \ + 0x200999, 0x200ccc \ } #define ZYD_MAXIM2_PHY \ @@ -1226,6 +1219,8 @@ struct zyd_rf { /* RF attributes */ struct zyd_softc *rf_sc; /* back-pointer */ int width; + int idx; /* for GIT RF */ + int update_pwr; }; struct zyd_rq { diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c index ff86e36..d88f49c 100644 --- a/sys/fs/devfs/devfs_vfsops.c +++ b/sys/fs/devfs/devfs_vfsops.c @@ -34,6 +34,8 @@ * $FreeBSD$ */ +#include "opt_mac.h" /* To set MNT_MULTILABEL. */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 3cc6f22..82527a6 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -367,7 +367,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, active_cred, file_cred, struct iovec aiov; struct mount *mp; struct ucred *cred; - int error; + int error, lock_flags; VFS_ASSERT_GIANT(vp->v_mount); @@ -378,7 +378,13 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, active_cred, file_cred, (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) return (error); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (mp != NULL && + (mp->mnt_kern_flag & MNTK_SHARED_WRITES)) { + lock_flags = LK_SHARED; + } else { + lock_flags = LK_EXCLUSIVE; + } + vn_lock(vp, lock_flags | LK_RETRY); } else vn_lock(vp, LK_SHARED | LK_RETRY); @@ -564,7 +570,7 @@ vn_write(fp, uio, active_cred, flags, td) { struct vnode *vp; struct mount *mp; - int error, ioflag; + int error, ioflag, lock_flags; int vfslocked; KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", @@ -587,7 +593,15 @@ vn_write(fp, uio, active_cred, flags, td) if (vp->v_type != VCHR && (error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) goto unlock; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + + if (mp != NULL && (mp->mnt_kern_flag & MNTK_SHARED_WRITES) && + (flags & FOF_OFFSET) != 0) { + lock_flags = LK_SHARED; + } else { + lock_flags = LK_EXCLUSIVE; + } + + vn_lock(vp, lock_flags | LK_RETRY); if ((flags & FOF_OFFSET) == 0) uio->uio_offset = fp->f_offset; ioflag |= sequential_heuristic(uio, fp); diff --git a/sys/modules/usb/zyd/Makefile b/sys/modules/usb/zyd/Makefile index 10711f9..48dd9eb 100644 --- a/sys/modules/usb/zyd/Makefile +++ b/sys/modules/usb/zyd/Makefile @@ -31,6 +31,6 @@ S= ${.CURDIR}/../../.. KMOD= if_zyd SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \ - if_zyd.c + if_zyd.c if_zydreg.h if_zydfw.h .include <bsd.kmod.mk> diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index d9b4c54..88e781c 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -686,7 +686,7 @@ enum { IEEE80211_ELEMID_TPCREQ = 34, IEEE80211_ELEMID_TPCREP = 35, IEEE80211_ELEMID_SUPPCHAN = 36, - IEEE80211_ELEMID_CHANSWITCHANN = 37, + IEEE80211_ELEMID_CSA = 37, IEEE80211_ELEMID_MEASREQ = 38, IEEE80211_ELEMID_MEASREP = 39, IEEE80211_ELEMID_QUIET = 40, @@ -736,6 +736,14 @@ struct ieee80211_csa_ie { uint8_t csa_count; /* Channel Switch Count */ } __packed; +/* + * Note the min acceptable CSA count is used to guard against + * malicious CSA injection in station mode. Defining this value + * as other than 0 violates the 11h spec. + */ +#define IEEE80211_CSA_COUNT_MIN 2 +#define IEEE80211_CSA_COUNT_MAX 255 + /* rate set entries are in .5 Mb/s units, and potentially marked as basic */ #define IEEE80211_RATE_BASIC 0x80 #define IEEE80211_RATE_VAL 0x7f diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index eec52f9..625ee98 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -114,6 +114,41 @@ sta_disassoc(void *arg, struct ieee80211_node *ni) } } +static void +sta_csa(void *arg, struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = arg; + + if (ni->ni_vap == vap && ni->ni_associd != 0) + if (ni->ni_inact > vap->iv_inact_init) { + ni->ni_inact = vap->iv_inact_init; + IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni, + "%s: inact %u", __func__, ni->ni_inact); + } +} + +static void +sta_drop(void *arg, struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = arg; + + if (ni->ni_vap == vap && ni->ni_associd != 0) + ieee80211_node_leave(ni); +} + +/* + * Does a channel change require associated stations to re-associate + * so protocol state is correct. This is used when doing CSA across + * bands or similar (e.g. HT -> legacy). + */ +static int +isbandchange(struct ieee80211com *ic) +{ + return ((ic->ic_bsschan->ic_flags ^ ic->ic_csa_newchan->ic_flags) & + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_HALF | + IEEE80211_CHAN_QUARTER | IEEE80211_CHAN_HT)) != 0; +} + /* * IEEE80211_M_HOSTAP vap state machine handler. */ @@ -249,6 +284,11 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* fall thru... */ case IEEE80211_S_CSA: /* + * Shorten inactivity timer of associated stations + * to weed out sta's that don't follow a CSA. + */ + ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap); + /* * Update bss node channel to reflect where * we landed after CSA. */ @@ -289,6 +329,18 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } ieee80211_node_authorize(vap->iv_bss); break; + case IEEE80211_S_CSA: + if (ostate == IEEE80211_S_RUN && isbandchange(ic)) { + /* + * On a ``band change'' silently drop associated + * stations as they must re-associate before they + * can pass traffic (as otherwise protocol state + * such as capabilities and the negotiated rate + * set may/will be wrong). + */ + ieee80211_iterate_nodes(&ic->ic_sta, sta_drop, vap); + } + break; default: break; } diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 53c2285..ad3fab4 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -475,6 +475,7 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m, * [tlv] ssid * [tlv] supported rates * [tlv] country information + * [tlv] channel switch announcement (CSA) * [tlv] parameter set (FH/DS) * [tlv] erp information * [tlv] extended supported rates @@ -508,6 +509,9 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m, case IEEE80211_ELEMID_COUNTRY: scan->country = frm; break; + case IEEE80211_ELEMID_CSA: + scan->csa = frm; + break; case IEEE80211_ELEMID_FHPARMS: if (ic->ic_phytype == IEEE80211_T_FH) { scan->fhdwell = LE_READ_2(&frm[2]); @@ -642,6 +646,14 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m, IEEE80211_VERIFY_LENGTH(scan->country[1], 3 * sizeof(uint8_t), scan->country = NULL); } + if (scan->csa != NULL) { + /* + * Validate Channel Switch Announcement; this must + * be the correct length or we toss the frame. + */ + IEEE80211_VERIFY_LENGTH(scan->csa[1], 3 * sizeof(uint8_t), + scan->status |= IEEE80211_BPARSE_CSA_INVALID); + } /* * Process HT ie's. This is complicated by our * accepting both the standard ie's and the pre-draft diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 36c6f4c..d88f812 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -2304,8 +2304,10 @@ ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq) error = copyin(ireq->i_data, &csr, sizeof(csr)); if (error != 0) return error; - if ((vap->iv_flags & IEEE80211_F_DOTH) == 0) - return EINVAL; + /* XXX adhoc mode not supported */ + if (vap->iv_opmode != IEEE80211_M_HOSTAP || + (vap->iv_flags & IEEE80211_F_DOTH) == 0) + return EOPNOTSUPP; c = ieee80211_find_channel(ic, csr.csa_chan.ic_freq, csr.csa_chan.ic_flags); if (c == NULL) @@ -2313,6 +2315,8 @@ ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq) IEEE80211_LOCK(ic); if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) ieee80211_csa_startswitch(ic, c, csr.csa_mode, csr.csa_count); + else if (csr.csa_count == 0) + ieee80211_csa_cancelswitch(ic); else error = EBUSY; IEEE80211_UNLOCK(ic); diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index a46b228..602ab7a 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -1468,7 +1468,7 @@ ieee80211_add_csa(uint8_t *frm, struct ieee80211vap *vap) struct ieee80211com *ic = vap->iv_ic; struct ieee80211_csa_ie *csa = (struct ieee80211_csa_ie *) frm; - csa->csa_ie = IEEE80211_ELEMID_CHANSWITCHANN; + csa->csa_ie = IEEE80211_ELEMID_CSA; csa->csa_len = 3; csa->csa_mode = 1; /* XXX force quiet on channel */ csa->csa_newchan = ieee80211_chan2ieee(ic, ic->ic_csa_newchan); diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 7e69929..9f80cdf 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -1374,7 +1374,7 @@ beacon_miss(void *arg, int npending) * handlers duplicating these checks. */ if (vap->iv_opmode == IEEE80211_M_STA && - vap->iv_state == IEEE80211_S_RUN && + vap->iv_state >= IEEE80211_S_RUN && vap->iv_bmiss != NULL) vap->iv_bmiss(vap); } @@ -1451,8 +1451,8 @@ ieee80211_csa_startswitch(struct ieee80211com *ic, IEEE80211_LOCK_ASSERT(ic); ic->ic_csa_newchan = c; + ic->ic_csa_mode = mode; ic->ic_csa_count = count; - /* XXX record mode? */ ic->ic_flags |= IEEE80211_F_CSAPENDING; TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -1465,6 +1465,19 @@ ieee80211_csa_startswitch(struct ieee80211com *ic, ieee80211_notify_csa(ic, c, mode, count); } +static void +csa_completeswitch(struct ieee80211com *ic) +{ + struct ieee80211vap *vap; + + ic->ic_csa_newchan = NULL; + ic->ic_flags &= ~IEEE80211_F_CSAPENDING; + + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if (vap->iv_state == IEEE80211_S_CSA) + ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0); +} + /* * Complete an 802.11h channel switch started by ieee80211_csa_startswitch. * We clear state and move all vap's in CSA state to RUN state @@ -1473,19 +1486,25 @@ ieee80211_csa_startswitch(struct ieee80211com *ic, void ieee80211_csa_completeswitch(struct ieee80211com *ic) { - struct ieee80211vap *vap; - IEEE80211_LOCK_ASSERT(ic); KASSERT(ic->ic_flags & IEEE80211_F_CSAPENDING, ("csa not pending")); ieee80211_setcurchan(ic, ic->ic_csa_newchan); - ic->ic_csa_newchan = NULL; - ic->ic_flags &= ~IEEE80211_F_CSAPENDING; + csa_completeswitch(ic); +} - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) - if (vap->iv_state == IEEE80211_S_CSA) - ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0); +/* + * Cancel an 802.11h channel switch started by ieee80211_csa_startswitch. + * We clear state and move all vap's in CSA state to RUN state + * so they can again transmit. + */ +void +ieee80211_csa_cancelswitch(struct ieee80211com *ic) +{ + IEEE80211_LOCK_ASSERT(ic); + + csa_completeswitch(ic); } /* diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index c9c3f07..3afb551 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -340,6 +340,7 @@ int ieee80211_beacon_update(struct ieee80211_node *, void ieee80211_csa_startswitch(struct ieee80211com *, struct ieee80211_channel *, int mode, int count); void ieee80211_csa_completeswitch(struct ieee80211com *); +void ieee80211_csa_cancelswitch(struct ieee80211com *); void ieee80211_cac_completeswitch(struct ieee80211vap *); /* diff --git a/sys/net80211/ieee80211_scan.h b/sys/net80211/ieee80211_scan.h index 9b4192e..ac44474 100644 --- a/sys/net80211/ieee80211_scan.h +++ b/sys/net80211/ieee80211_scan.h @@ -176,6 +176,7 @@ enum { IEEE80211_BPARSE_CHAN_INVALID = 0x10, /* invalid FH/DSPARMS chan */ IEEE80211_BPARSE_OFFCHAN = 0x20, /* DSPARMS chan != curchan */ IEEE80211_BPARSE_BINTVAL_INVALID= 0x40, /* invalid beacon interval */ + IEEE80211_BPARSE_CSA_INVALID = 0x80, /* invalid CSA ie */ }; /* @@ -211,7 +212,8 @@ struct ieee80211_scanparams { uint8_t *htinfo; uint8_t *ath; uint8_t *tdma; - uint8_t *spare[4]; + uint8_t *csa; + uint8_t *spare[3]; }; /* diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 0dee283..097d2f2 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -106,15 +106,28 @@ sta_vattach(struct ieee80211vap *vap) static void sta_beacon_miss(struct ieee80211vap *vap) { - KASSERT((vap->iv_ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scanning")); - KASSERT(vap->iv_state == IEEE80211_S_RUN, - ("wrong state %d", vap->iv_state)); + struct ieee80211com *ic = vap->iv_ic; + + KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scanning")); + KASSERT(vap->iv_state >= IEEE80211_S_RUN, + ("wrong state %s", ieee80211_state_name[vap->iv_state])); - IEEE80211_DPRINTF(vap, - IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, - "beacon miss, mode %u state %s\n", - vap->iv_opmode, ieee80211_state_name[vap->iv_state]); + IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, + "beacon miss, mode %s state %s\n", + ieee80211_opmode_name[vap->iv_opmode], + ieee80211_state_name[vap->iv_state]); + if (vap->iv_state == IEEE80211_S_CSA) { + /* + * A Channel Switch is pending; assume we missed the + * beacon that would've completed the process and just + * force the switch. If we made a mistake we'll not + * find the AP on the new channel and fall back to a + * normal scan. + */ + ieee80211_csa_completeswitch(ic); + return; + } if (++vap->iv_bmiss_count < vap->iv_bmiss_max) { /* * Send a directed probe req before falling back to a @@ -359,6 +372,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } switch (ostate) { case IEEE80211_S_RUN: + case IEEE80211_S_CSA: break; case IEEE80211_S_AUTH: /* when join is done in fw */ case IEEE80211_S_ASSOC: @@ -412,6 +426,10 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (ic->ic_newassoc != NULL) ic->ic_newassoc(vap->iv_bss, ostate != IEEE80211_S_RUN); break; + case IEEE80211_S_CSA: + if (ostate != IEEE80211_S_RUN) + goto invalid; + break; case IEEE80211_S_SLEEP: ieee80211_sta_pwrsave(vap, 0); break; @@ -1080,6 +1098,112 @@ ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm, } /* + * Process 11h Channel Switch Announcement (CSA) ie. If this + * is the first CSA then initiate the switch. Otherwise we + * track state and trigger completion and/or cancel of the switch. + * XXX should be public for IBSS use + */ +static void +ieee80211_parse_csaparams(struct ieee80211vap *vap, uint8_t *frm, + const struct ieee80211_frame *wh) +{ + struct ieee80211com *ic = vap->iv_ic; + const struct ieee80211_csa_ie *csa = + (const struct ieee80211_csa_ie *) frm; + + KASSERT(vap->iv_state >= IEEE80211_S_RUN, + ("state %s", ieee80211_state_name[vap->iv_state])); + + if (csa->csa_mode > 1) { + IEEE80211_DISCARD_IE(vap, + IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH, + wh, "CSA", "invalid mode %u", csa->csa_mode); + return; + } + IEEE80211_LOCK(ic); + if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) { + /* + * Convert the channel number to a channel reference. We + * try first to preserve turbo attribute of the current + * channel then fallback. Note this will not work if the + * CSA specifies a channel that requires a band switch (e.g. + * 11a => 11g). This is intentional as 11h is defined only + * for 5GHz/11a and because the switch does not involve a + * reassociation, protocol state (capabilities, negotated + * rates, etc) may/will be wrong. + */ + struct ieee80211_channel *c = + ieee80211_find_channel_byieee(ic, csa->csa_newchan, + (ic->ic_bsschan->ic_flags & IEEE80211_CHAN_ALLTURBO)); + if (c == NULL) { + c = ieee80211_find_channel_byieee(ic, + csa->csa_newchan, + (ic->ic_bsschan->ic_flags & IEEE80211_CHAN_ALL)); + if (c == NULL) { + IEEE80211_DISCARD_IE(vap, + IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH, + wh, "CSA", "invalid channel %u", + csa->csa_newchan); + goto done; + } + } +#if IEEE80211_CSA_COUNT_MIN > 0 + if (csa->csa_count < IEEE80211_CSA_COUNT_MIN) { + /* + * Require at least IEEE80211_CSA_COUNT_MIN count to + * reduce the risk of being redirected by a fabricated + * CSA. If a valid CSA is dropped we'll still get a + * beacon miss when the AP leaves the channel so we'll + * eventually follow to the new channel. + * + * NOTE: this violates the 11h spec that states that + * count may be any value and if 0 then a switch + * should happen asap. + */ + IEEE80211_DISCARD_IE(vap, + IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH, + wh, "CSA", "count %u too small, must be >= %u", + csa->csa_count, IEEE80211_CSA_COUNT_MIN); + goto done; + } +#endif + ieee80211_csa_startswitch(ic, c, csa->csa_mode, csa->csa_count); + } else { + /* + * Validate this ie against the initial CSA. We require + * mode and channel not change and the count must be + * monotonically decreasing. This may be pointless and + * canceling the switch as a result may be too paranoid but + * in the worst case if we drop out of CSA because of this + * and the AP does move then we'll just end up taking a + * beacon miss and scan to find the AP. + * + * XXX may want <= on count as we also process ProbeResp + * frames and those may come in w/ the same count as the + * previous beacon; but doing so leaves us open to a stuck + * count until we add a dead-man timer + */ + if (!(csa->csa_count < ic->ic_csa_count && + csa->csa_mode == ic->ic_csa_mode && + csa->csa_newchan == ieee80211_chan2ieee(ic, ic->ic_csa_newchan))) { + IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_DOTH, wh, + "CSA ie mismatch, initial ie <%d,%d,%d>, " + "this ie <%d,%d,%d>", ic->ic_csa_mode, + ic->ic_csa_newchan, ic->ic_csa_count, + csa->csa_mode, csa->csa_newchan, csa->csa_count); + ieee80211_csa_cancelswitch(ic); + } else { + if (csa->csa_count <= 1) + ieee80211_csa_completeswitch(ic); + else + ic->ic_csa_count = csa->csa_count; + } + } +done: + IEEE80211_UNLOCK(ic); +} + +/* * Return non-zero if a background scan may be continued: * o bg scan is active * o no channel switch is pending @@ -1245,6 +1369,20 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, ni->ni_dtim_count = tim->tim_count; ni->ni_dtim_period = tim->tim_period; } + if (scan.csa != NULL && + (vap->iv_flags & IEEE80211_F_DOTH)) + ieee80211_parse_csaparams(vap, scan.csa, wh); + else if (ic->ic_flags & IEEE80211_F_CSAPENDING) { + /* + * No CSA ie or 11h disabled, but a channel + * switch is pending; drop out so we aren't + * stuck in CSA state. If the AP really is + * moving we'll get a beacon miss and scan. + */ + IEEE80211_LOCK(ic); + ieee80211_csa_cancelswitch(ic); + IEEE80211_UNLOCK(ic); + } /* * If scanning, pass the info to the scan module. * Otherwise, check if it's the right time to do diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 3e999c8..df7575f 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -181,7 +181,8 @@ struct ieee80211com { /* 802.11h/DFS state */ struct ieee80211_channel *ic_csa_newchan;/* channel for doing CSA */ - int ic_csa_count; /* count for doing CSA */ + short ic_csa_mode; /* mode for doing CSA */ + short ic_csa_count; /* count for doing CSA */ struct ieee80211_dfs_state ic_dfs; /* DFS state */ struct ieee80211_scan_state *ic_scan; /* scan state */ diff --git a/sys/netinet/ip_dummynet.h b/sys/netinet/ip_dummynet.h index 6e102f4..43e6842 100644 --- a/sys/netinet/ip_dummynet.h +++ b/sys/netinet/ip_dummynet.h @@ -214,8 +214,8 @@ struct dn_flow_queue { * With large bandwidth and large delays, extra_bits (and also numbytes) * can become very large, so better play safe and use 64 bit */ - dn_key numbytes ; /* credit for transmission (dynamic queues) */ - dn_key extra_bits; /* extra bits simulating unavailable channel */ + uint64_t numbytes ; /* credit for transmission (dynamic queues) */ + int64_t extra_bits; /* extra bits simulating unavailable channel */ u_int64_t tot_pkts ; /* statistics counters */ u_int64_t tot_bytes ; @@ -338,7 +338,7 @@ struct dn_pipe { /* a pipe */ int sum; /* sum of weights of all active sessions */ /* Same as in dn_flow_queue, numbytes can become large */ - dn_key numbytes; /* bits I can transmit (more or less). */ + int64_t numbytes; /* bits I can transmit (more or less). */ dn_key sched_time ; /* time pipe was scheduled in ready_heap */ diff --git a/sys/nlm/nlm_advlock.c b/sys/nlm/nlm_advlock.c index 0be799d..029f77b 100644 --- a/sys/nlm/nlm_advlock.c +++ b/sys/nlm/nlm_advlock.c @@ -716,8 +716,8 @@ nlm_record_lock(struct vnode *vp, int op, struct flock *fl, newfl.l_sysid = NLM_SYSID_CLIENT | sysid; error = lf_advlockasync(&a, &vp->v_lockf, size); - KASSERT(error == 0, ("Failed to register NFS lock locally - error=%d", - error)); + KASSERT(error == 0 || error == ENOENT, + ("Failed to register NFS lock locally - error=%d", error)); } static int diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c index 880a16f..865c704 100644 --- a/sys/rpc/clnt_dg.c +++ b/sys/rpc/clnt_dg.c @@ -123,8 +123,11 @@ struct cu_socket { struct mtx cs_lock; int cs_refs; /* Count of clients */ struct cu_request_list cs_pending; /* Requests awaiting replies */ + int cs_upcallrefs; /* Refcnt of upcalls in prog.*/ }; +static void clnt_dg_upcallsdone(struct socket *, struct cu_socket *); + /* * Private data kept per client handle */ @@ -291,6 +294,7 @@ recheck_socket: } mtx_init(&cs->cs_lock, "cs->cs_lock", NULL, MTX_DEF); cs->cs_refs = 1; + cs->cs_upcallrefs = 0; TAILQ_INIT(&cs->cs_pending); soupcall_set(so, SO_RCV, clnt_dg_soupcall, cs); } @@ -988,10 +992,12 @@ clnt_dg_destroy(CLIENT *cl) cs->cs_refs--; if (cs->cs_refs == 0) { - mtx_destroy(&cs->cs_lock); + mtx_unlock(&cs->cs_lock); SOCKBUF_LOCK(&cu->cu_socket->so_rcv); soupcall_clear(cu->cu_socket, SO_RCV); + clnt_dg_upcallsdone(cu->cu_socket, cs); SOCKBUF_UNLOCK(&cu->cu_socket->so_rcv); + mtx_destroy(&cs->cs_lock); mem_free(cs, sizeof(*cs)); lastsocketref = TRUE; } else { @@ -1036,6 +1042,7 @@ clnt_dg_soupcall(struct socket *so, void *arg, int waitflag) int error, rcvflag, foundreq; uint32_t xid; + cs->cs_upcallrefs++; uio.uio_resid = 1000000000; uio.uio_td = curthread; do { @@ -1111,6 +1118,24 @@ clnt_dg_soupcall(struct socket *so, void *arg, int waitflag) if (!foundreq) m_freem(m); } while (m); + cs->cs_upcallrefs--; + if (cs->cs_upcallrefs < 0) + panic("rpcdg upcall refcnt"); + if (cs->cs_upcallrefs == 0) + wakeup(&cs->cs_upcallrefs); return (SU_OK); } +/* + * Wait for all upcalls in progress to complete. + */ +static void +clnt_dg_upcallsdone(struct socket *so, struct cu_socket *cs) +{ + + SOCKBUF_LOCK_ASSERT(&so->so_rcv); + + while (cs->cs_upcallrefs > 0) + (void) msleep(&cs->cs_upcallrefs, SOCKBUF_MTX(&so->so_rcv), 0, + "rpcdgup", 0); +} diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c index f094945..4e732f2 100644 --- a/sys/rpc/clnt_vc.c +++ b/sys/rpc/clnt_vc.c @@ -137,8 +137,11 @@ struct ct_data { size_t ct_record_resid; /* how much left of reply to read */ bool_t ct_record_eor; /* true if reading last fragment */ struct ct_request_list ct_pending; + int ct_upcallrefs; /* Ref cnt of upcalls in prog. */ }; +static void clnt_vc_upcallsdone(struct ct_data *); + static const char clnt_vc_errstr[] = "%s : %s"; static const char clnt_vc_str[] = "clnt_vc_create"; static const char clnt_read_vc_str[] = "read_vc"; @@ -184,6 +187,7 @@ clnt_vc_create( ct->ct_threads = 0; ct->ct_closing = FALSE; ct->ct_closed = FALSE; + ct->ct_upcallrefs = 0; if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { error = soconnect(so, raddr, curthread); @@ -753,6 +757,7 @@ clnt_vc_close(CLIENT *cl) SOCKBUF_LOCK(&ct->ct_socket->so_rcv); soupcall_clear(ct->ct_socket, SO_RCV); + clnt_vc_upcallsdone(ct); SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv); /* @@ -825,6 +830,7 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag) uint32_t xid, header; bool_t do_read; + ct->ct_upcallrefs++; uio.uio_td = curthread; do { /* @@ -845,7 +851,7 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag) do_read = TRUE; if (!do_read) - return (SU_OK); + break; SOCKBUF_UNLOCK(&so->so_rcv); uio.uio_resid = sizeof(uint32_t); @@ -898,7 +904,7 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag) do_read = TRUE; if (!do_read) - return (SU_OK); + break; /* * We have the record mark. Read as much as @@ -979,5 +985,24 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag) } } } while (m); + ct->ct_upcallrefs--; + if (ct->ct_upcallrefs < 0) + panic("rpcvc upcall refcnt"); + if (ct->ct_upcallrefs == 0) + wakeup(&ct->ct_upcallrefs); return (SU_OK); } + +/* + * Wait for all upcalls in progress to complete. + */ +static void +clnt_vc_upcallsdone(struct ct_data *ct) +{ + + SOCKBUF_LOCK_ASSERT(&ct->ct_socket->so_rcv); + + while (ct->ct_upcallrefs > 0) + (void) msleep(&ct->ct_upcallrefs, + SOCKBUF_MTX(&ct->ct_socket->so_rcv), 0, "rpcvcup", 0); +} diff --git a/sys/rpc/svc.c b/sys/rpc/svc.c index 8af9e80..fbddafb 100644 --- a/sys/rpc/svc.c +++ b/sys/rpc/svc.c @@ -175,12 +175,12 @@ svcpool_destroy(SVCPOOL *pool) mtx_lock(&pool->sp_lock); } - mtx_destroy(&pool->sp_lock); - TAILQ_FOREACH_SAFE(xprt, &cleanup, xp_link, nxprt) { SVC_RELEASE(xprt); } + mtx_destroy(&pool->sp_lock); + if (pool->sp_rcache) replay_freecache(pool->sp_rcache); @@ -353,15 +353,16 @@ xprt_active(SVCXPRT *xprt) { SVCPOOL *pool = xprt->xp_pool; + mtx_lock(&pool->sp_lock); + if (!xprt->xp_registered) { /* * Race with xprt_unregister - we lose. */ + mtx_unlock(&pool->sp_lock); return; } - mtx_lock(&pool->sp_lock); - if (!xprt->xp_active) { TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); xprt->xp_active = TRUE; diff --git a/sys/rpc/svc.h b/sys/rpc/svc.h index 73c4414..1bd3054 100644 --- a/sys/rpc/svc.h +++ b/sys/rpc/svc.h @@ -166,6 +166,7 @@ typedef struct __rpc_svcxprt { int xp_idletimeout; /* idle time before closing */ time_t xp_lastactive; /* time of last RPC */ u_int64_t xp_sockref; /* set by nfsv4 to identify socket */ + int xp_upcallset; /* socket upcall is set up */ #else int xp_fd; u_short xp_port; /* associated port number */ diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index be366de..7249270 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -160,6 +160,7 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, solisten(so, SOMAXCONN, curthread); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -234,6 +235,7 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) xprt_register(xprt); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -352,7 +354,10 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); sx_xunlock(&xprt->xp_lock); @@ -397,7 +402,10 @@ static void svc_vc_destroy_common(SVCXPRT *xprt) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); sx_destroy(&xprt->xp_lock); @@ -632,7 +640,10 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); cd->strm_stat = XPRT_DIED; diff --git a/sys/sys/mount.h b/sys/sys/mount.h index f59a06e..a7915d6 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -326,6 +326,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp); #define MNTK_DRAINING 0x00000010 /* lock draining is happening */ #define MNTK_REFEXPIRE 0x00000020 /* refcount expiring is happening */ #define MNTK_EXTENDED_SHARED 0x00000040 /* Allow shared locking for more ops */ +#define MNTK_SHARED_WRITES 0x00000080 /* Allow shared locking for writes */ #define MNTK_UNMOUNT 0x01000000 /* unmount in progress */ #define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */ #define MNTK_SUSPEND 0x08000000 /* request write suspension */ |