Resync with head.
This commit is contained in:
commit
d042da967c
@ -2888,7 +2888,7 @@ iename(int elemid)
|
||||
case IEEE80211_ELEMID_TPCREQ: return " TPCREQ";
|
||||
case IEEE80211_ELEMID_TPCREP: return " TPCREP";
|
||||
case IEEE80211_ELEMID_SUPPCHAN: return " SUPPCHAN";
|
||||
case IEEE80211_ELEMID_CHANSWITCHANN:return " CSA";
|
||||
case IEEE80211_ELEMID_CSA: return " CSA";
|
||||
case IEEE80211_ELEMID_MEASREQ: return " MEASREQ";
|
||||
case IEEE80211_ELEMID_MEASREP: return " MEASREP";
|
||||
case IEEE80211_ELEMID_QUIET: return " QUIET";
|
||||
|
@ -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;
|
||||
|
@ -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,119 +1440,150 @@ 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_mode(struct zyd_rf *rf)
|
||||
{
|
||||
#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;
|
||||
|
||||
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_synth(struct zyd_rf *rf, int chan, int acal)
|
||||
{
|
||||
int error, idx = chan - 1;
|
||||
struct zyd_softc *sc = rf->rf_sc;
|
||||
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,
|
||||
(acal == 1) ? acal_synth[idx] : std_synth[idx]);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
return zyd_rfwrite(sc, div_synth[idx]);
|
||||
}
|
||||
|
||||
static int
|
||||
zyd_gct_write(struct zyd_rf *rf, uint16_t value)
|
||||
{
|
||||
struct zyd_softc *sc = rf->rf_sc;
|
||||
|
||||
return zyd_rfwrite(sc, 0x300000 | 0x40000 | value);
|
||||
}
|
||||
|
||||
static int
|
||||
zyd_gct_switch_radio(struct zyd_rf *rf, int on)
|
||||
{
|
||||
/* vendor driver does nothing for this RF chip */
|
||||
#define N(a) (sizeof(a) / sizeof((a)[0]))
|
||||
int error;
|
||||
struct zyd_softc *sc = rf->rf_sc;
|
||||
|
||||
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_gct_set_channel(struct zyd_rf *rf, uint8_t chan)
|
||||
{
|
||||
int error;
|
||||
struct zyd_softc *sc = rf->rf_sc;
|
||||
static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE;
|
||||
|
||||
error = zyd_rfwrite(sc, 0x1c0000);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
error = zyd_rfwrite(sc, rfprog[chan - 1]);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
error = zyd_rfwrite(sc, 0x1c0008);
|
||||
fail:
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maxim RF methods.
|
||||
*/
|
||||
static int
|
||||
zyd_maxim_init(struct zyd_rf *rf)
|
||||
{
|
||||
#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;
|
||||
uint16_t tmp;
|
||||
int i, error;
|
||||
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;
|
||||
|
||||
/* 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));
|
||||
error = zyd_gct_set_channel_synth(rf, chan, 0);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
error = zyd_gct_write(rf, (rf->idx == -1) ? 0x6662 :
|
||||
vco[rf->idx][((chan - 1) / 2)]);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
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_maxim_switch_radio(struct zyd_rf *rf, int on)
|
||||
{
|
||||
|
||||
/* vendor driver does nothing for this RF chip */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan)
|
||||
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 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;
|
||||
static uint32_t txgain[] = ZYD_GCT_TXGAIN;
|
||||
uint8_t idx = sc->sc_pwrint[chan - 1];
|
||||
|
||||
/*
|
||||
* 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));
|
||||
|
||||
/* first two values taken from the chantables */
|
||||
error = zyd_rfwrite(sc, rfprog[chan - 1].r1);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
error = zyd_rfwrite(sc, rfprog[chan - 1].r2);
|
||||
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);
|
||||
if (idx >= N(txgain)) {
|
||||
device_printf(sc->sc_dev, "could not set TX gain (%d %#x)\n",
|
||||
chan, idx);
|
||||
return 0;
|
||||
}
|
||||
zyd_read16_m(sc, ZYD_CR203, &tmp);
|
||||
zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4));
|
||||
fail:
|
||||
return (error);
|
||||
|
||||
return zyd_rfwrite(sc, 0x700000 | txgain[idx]);
|
||||
#undef N
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
@ -248,6 +283,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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 *);
|
||||
|
||||
/*
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
||||
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]);
|
||||
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 %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;
|
||||
@ -1079,6 +1097,112 @@ ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm,
|
||||
#undef MS
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user