diff options
author | jkim <jkim@FreeBSD.org> | 2009-06-03 22:54:27 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2009-06-03 22:54:27 +0000 |
commit | 8b4d37b6a77bc5293cb64640e5e438e517676aa3 (patch) | |
tree | c84ae4a93183dfcb38f5e0f2bfa127f31847bbc6 /sys | |
parent | feac47ed6a1eb54eff18f1d19649bc92dbf7af87 (diff) | |
parent | 6b340c06d17352b1fd07ec2fe19a9c83af9e9e5b (diff) | |
download | FreeBSD-src-8b4d37b6a77bc5293cb64640e5e438e517676aa3.zip FreeBSD-src-8b4d37b6a77bc5293cb64640e5e438e517676aa3.tar.gz |
Resync with head.
Diffstat (limited to 'sys')
91 files changed, 1588 insertions, 1353 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 569e0cd..6ff85e2 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -70,6 +70,7 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev options STOP_NMI # Stop CPUS using NMI instead of IPI options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing +options MAC # TrustedBSD MAC Framework #options KDTRACE_FRAME # Ensure frames are compiled in #options KDTRACE_HOOKS # Kernel DTrace hooks diff --git a/sys/amd64/conf/MAC b/sys/amd64/conf/MAC deleted file mode 100644 index 306f36f..0000000 --- a/sys/amd64/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/amd64 MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/boot/uboot/lib/disk.c b/sys/boot/uboot/lib/disk.c index 1725d07..4cbdbea 100644 --- a/sys/boot/uboot/lib/disk.c +++ b/sys/boot/uboot/lib/disk.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/endian.h> #include <sys/queue.h> #include <netinet/in.h> #include <machine/stdarg.h> @@ -122,6 +123,15 @@ struct devsw uboot_storage = { stor_print }; +static void +uuid_letoh(uuid_t *uuid) +{ + + uuid->time_low = le32toh(uuid->time_low); + uuid->time_mid = le16toh(uuid->time_mid); + uuid->time_hi_and_version = le16toh(uuid->time_hi_and_version); +} + static int stor_init(void) { @@ -251,7 +261,7 @@ stor_open_gpt(struct open_dev *od, struct uboot_devdesc *dev) } /* Check the slice table magic. */ - if (*((uint16_t *)(buf + DOSMAGICOFFSET)) != DOSMAGIC) { + if (le16toh(*((uint16_t *)(buf + DOSMAGICOFFSET))) != DOSMAGIC) { err = ENXIO; goto out; } @@ -286,9 +296,10 @@ stor_open_gpt(struct open_dev *od, struct uboot_devdesc *dev) /* Check GPT header */ if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 || - hdr->hdr_lba_self != 1 || hdr->hdr_revision < 0x00010000 || - hdr->hdr_entsz < sizeof(*ent) || - od->od_bsize % hdr->hdr_entsz != 0) { + le64toh(hdr->hdr_lba_self) != 1 || + le32toh(hdr->hdr_revision) < 0x00010000 || + le32toh(hdr->hdr_entsz) < sizeof(*ent) || + od->od_bsize % le32toh(hdr->hdr_entsz) != 0) { debugf("Invalid GPT header!\n"); err = EINVAL; goto out; @@ -296,9 +307,9 @@ stor_open_gpt(struct open_dev *od, struct uboot_devdesc *dev) /* Count number of valid partitions */ part = 0; - eps = od->od_bsize / hdr->hdr_entsz; - slba = hdr->hdr_lba_table; - elba = slba + hdr->hdr_entries / eps; + eps = od->od_bsize / le32toh(hdr->hdr_entsz); + slba = le64toh(hdr->hdr_lba_table); + elba = slba + le32toh(hdr->hdr_entries) / eps; for (lba = slba; lba < elba; lba++) { err = stor_readdev(dev, lba, 1, buf); @@ -312,8 +323,9 @@ stor_open_gpt(struct open_dev *od, struct uboot_devdesc *dev) for (i = 0; i < eps; i++) { if (uuid_is_nil(&ent[i].ent_type, NULL) || - ent[i].ent_lba_start == 0 || - ent[i].ent_lba_end < ent[i].ent_lba_start) + le64toh(ent[i].ent_lba_start) == 0 || + le64toh(ent[i].ent_lba_end) < + le64toh(ent[i].ent_lba_start)) continue; part += 1; @@ -343,8 +355,9 @@ stor_open_gpt(struct open_dev *od, struct uboot_devdesc *dev) for (i = 0; i < eps; i++) { if (uuid_is_nil(&ent[i].ent_type, NULL) || - ent[i].ent_lba_start == 0 || - ent[i].ent_lba_end < ent[i].ent_lba_start) + le64toh(ent[i].ent_lba_start) == 0 || + le64toh(ent[i].ent_lba_end) < + le64toh(ent[i].ent_lba_start)) continue; od->od_partitions[part].gp_index = (lba - slba) @@ -352,9 +365,11 @@ stor_open_gpt(struct open_dev *od, struct uboot_devdesc *dev) od->od_partitions[part].gp_type = ent[i].ent_type; od->od_partitions[part].gp_start = - ent[i].ent_lba_start; + le64toh(ent[i].ent_lba_start); od->od_partitions[part].gp_end = - ent[i].ent_lba_end; + le64toh(ent[i].ent_lba_end); + + uuid_letoh(&od->od_partitions[part].gp_type); part += 1; } } diff --git a/sys/dev/aic7xxx/aicasm/Makefile b/sys/dev/aic7xxx/aicasm/Makefile index 78701b0..222c96a 100644 --- a/sys/dev/aic7xxx/aicasm/Makefile +++ b/sys/dev/aic7xxx/aicasm/Makefile @@ -15,6 +15,7 @@ SRCS= ${GENHDRS} ${CSRCS} ${YSRCS} ${LSRCS} CLEANFILES+= ${GENHDRS} ${YSRCS:R:C/(.*)/\1.output/g} DPADD= ${LIBL} LDADD= -ll +WARNS?= 6 # Correct path for kernel builds # Don't rely on the kernel's .depend file diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index e22758f..b8ee9a0 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -149,11 +149,26 @@ /* SATA AHCI v1.0 register defines */ #define ATA_AHCI_CAP 0x00 #define ATA_AHCI_CAP_NPMASK 0x0000001f +#define ATA_AHCI_CAP_SXS 0x00000020 +#define ATA_AHCI_CAP_EMS 0x00000040 +#define ATA_AHCI_CAP_CCCS 0x00000080 +#define ATA_AHCI_CAP_NCS 0x00001F00 +#define ATA_AHCI_CAP_NCS_SHIFT 8 #define ATA_AHCI_CAP_PSC 0x00002000 #define ATA_AHCI_CAP_SSC 0x00004000 +#define ATA_AHCI_CAP_PMD 0x00008000 +#define ATA_AHCI_CAP_FBSS 0x00010000 #define ATA_AHCI_CAP_SPM 0x00020000 -#define ATA_AHCI_CAP_CLO 0x01000000 +#define ATA_AHCI_CAP_SAM 0x00080000 +#define ATA_AHCI_CAP_ISS 0x00F00000 +#define ATA_AHCI_CAP_ISS_SHIFT 20 +#define ATA_AHCI_CAP_SCLO 0x01000000 +#define ATA_AHCI_CAP_SAL 0x02000000 #define ATA_AHCI_CAP_SALP 0x04000000 +#define ATA_AHCI_CAP_SSS 0x08000000 +#define ATA_AHCI_CAP_SMPS 0x10000000 +#define ATA_AHCI_CAP_SSNTF 0x20000000 +#define ATA_AHCI_CAP_SNCQ 0x40000000 #define ATA_AHCI_CAP_64BIT 0x80000000 #define ATA_AHCI_GHC 0x04 diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c index 7037f4d..eb490ab 100644 --- a/sys/dev/ata/chipsets/ata-ahci.c +++ b/sys/dev/ata/chipsets/ata-ahci.c @@ -101,8 +101,8 @@ int ata_ahci_chipinit(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); - int error; - u_int32_t version; + int error, speed; + u_int32_t caps, version; /* if we have a memory BAR(5) we are likely on an AHCI part */ ctlr->r_type2 = SYS_RES_MEMORY; @@ -142,16 +142,45 @@ ata_ahci_chipinit(device_t dev) ctlr->suspend = ata_ahci_suspend; ctlr->resume = ata_ahci_ctlr_reset; - /* announce we support the HW */ - version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS); - device_printf(dev, - "AHCI Version %x%x.%x%x controller with %d ports PM %s\n", - (version >> 24) & 0xff, (version >> 16) & 0xff, - (version >> 8) & 0xff, version & 0xff, - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1, - (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) ? - "supported" : "not supported"); - return 0; + /* announce we support the HW */ + version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS); + caps = ATA_INL(ctlr->r_res2, ATA_AHCI_CAP); + speed = (caps & ATA_AHCI_CAP_ISS) >> ATA_AHCI_CAP_ISS_SHIFT; + device_printf(dev, + "AHCI v%x.%02x controller with %d %sGbps ports, PM %s\n", + ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f), + ((version >> 4) & 0xf0) + (version & 0x0f), + (caps & ATA_AHCI_CAP_NPMASK) + 1, + ((speed == 1) ? "1.5":((speed == 2) ? "3": + ((speed == 3) ? "6":"?"))), + (caps & ATA_AHCI_CAP_SPM) ? + "supported" : "not supported"); + if (bootverbose) { + device_printf(dev, "Caps:%s%s%s%s%s%s%s%s %sGbps", + (caps & ATA_AHCI_CAP_64BIT) ? " 64bit":"", + (caps & ATA_AHCI_CAP_SNCQ) ? " NCQ":"", + (caps & ATA_AHCI_CAP_SSNTF) ? " SNTF":"", + (caps & ATA_AHCI_CAP_SMPS) ? " MPS":"", + (caps & ATA_AHCI_CAP_SSS) ? " SS":"", + (caps & ATA_AHCI_CAP_SALP) ? " ALP":"", + (caps & ATA_AHCI_CAP_SAL) ? " AL":"", + (caps & ATA_AHCI_CAP_SCLO) ? " CLO":"", + ((speed == 1) ? "1.5":((speed == 2) ? "3": + ((speed == 3) ? "6":"?")))); + printf("%s%s%s%s%s%s %dcmd%s%s%s %dports\n", + (caps & ATA_AHCI_CAP_SAM) ? " AM":"", + (caps & ATA_AHCI_CAP_SPM) ? " PM":"", + (caps & ATA_AHCI_CAP_FBSS) ? " FBS":"", + (caps & ATA_AHCI_CAP_PMD) ? " PMD":"", + (caps & ATA_AHCI_CAP_SSC) ? " SSC":"", + (caps & ATA_AHCI_CAP_PSC) ? " PSC":"", + ((caps & ATA_AHCI_CAP_NCS) >> ATA_AHCI_CAP_NCS_SHIFT) + 1, + (caps & ATA_AHCI_CAP_CCCS) ? " CCC":"", + (caps & ATA_AHCI_CAP_EMS) ? " EM":"", + (caps & ATA_AHCI_CAP_SXS) ? " eSATA":"", + (caps & ATA_AHCI_CAP_NPMASK) + 1); + } + return 0; } int @@ -625,7 +654,7 @@ ata_ahci_clo(device_t dev) int timeout; /* issue Command List Override if supported */ - if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_CLO) { + if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SCLO) { cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); cmd |= ATA_AHCI_P_CMD_CLO; ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd); diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 05930e3..2413d19 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1153,8 +1153,14 @@ ath_vap_delete(struct ieee80211vap *vap) if (ath_startrecv(sc) != 0) if_printf(ifp, "%s: unable to restart recv logic\n", __func__); - if (sc->sc_beacons) - ath_beacon_config(sc, NULL); + if (sc->sc_beacons) { /* restart beacons */ +#ifdef IEEE80211_SUPPORT_TDMA + if (sc->sc_tdma) + ath_tdma_config(sc, NULL); + else +#endif + ath_beacon_config(sc, NULL); + } ath_hal_intrset(ah, sc->sc_imask); } } @@ -1652,13 +1658,13 @@ ath_reset(struct ifnet *ifp) * might change as a result. */ ath_chan_change(sc, ic->ic_curchan); - if (sc->sc_beacons) { + if (sc->sc_beacons) { /* restart beacons */ #ifdef IEEE80211_SUPPORT_TDMA if (sc->sc_tdma) ath_tdma_config(sc, NULL); else #endif - ath_beacon_config(sc, NULL); /* restart beacons */ + ath_beacon_config(sc, NULL); } ath_hal_intrset(ah, sc->sc_imask); @@ -1704,7 +1710,6 @@ _ath_getbuf_locked(struct ath_softc *sc) DPRINTF(sc, ATH_DEBUG_XMIT, "%s: %s\n", __func__, STAILQ_FIRST(&sc->sc_txbuf) == NULL ? "out of xmit buffers" : "xmit buffer busy"); - sc->sc_stats.ast_tx_nobuf++; } return bf; } @@ -1814,6 +1819,7 @@ ath_start(struct ifnet *ifp) DPRINTF(sc, ATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); sc->sc_stats.ast_tx_nofrag++; + ifp->if_oerrors++; ath_freetx(m); goto bad; } @@ -2796,7 +2802,7 @@ ath_beacon_proc(void *arg, int pending) slot = ((tsftu % ic->ic_lintval) * ATH_BCBUF) / ic->ic_lintval; vap = sc->sc_bslot[(slot+1) % ATH_BCBUF]; bfaddr = 0; - if (vap != NULL && vap->iv_state == IEEE80211_S_RUN) { + if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) { bf = ath_beacon_generate(sc, vap); if (bf != NULL) bfaddr = bf->bf_daddr; @@ -2806,7 +2812,7 @@ ath_beacon_proc(void *arg, int pending) for (slot = 0; slot < ATH_BCBUF; slot++) { vap = sc->sc_bslot[slot]; - if (vap != NULL && vap->iv_state == IEEE80211_S_RUN) { + if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) { bf = ath_beacon_generate(sc, vap); if (bf != NULL) { *bflink = bf->bf_daddr; @@ -2872,7 +2878,7 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) struct mbuf *m; int nmcastq, error; - KASSERT(vap->iv_state == IEEE80211_S_RUN, + KASSERT(vap->iv_state >= IEEE80211_S_RUN, ("not running, state %d", vap->iv_state)); KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer")); @@ -4126,7 +4132,7 @@ ath_txq_update(struct ath_softc *sc, int ac) /* * AIFS is zero so there's no pre-transmit wait. The * burst time defines the slot duration and is configured - * via sysctl. The QCU is setup to not do post-xmit + * through net80211. The QCU is setup to not do post-xmit * back off, lockout all lower-priority QCU's, and fire * off the DMA beacon alert timer which is setup based * on the slot configuration. @@ -5500,7 +5506,7 @@ ath_isanyrunningvaps(struct ieee80211vap *this) IEEE80211_LOCK_ASSERT(ic); TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - if (vap != this && vap->iv_state == IEEE80211_S_RUN) + if (vap != this && vap->iv_state >= IEEE80211_S_RUN) return 1; } return 0; @@ -6825,55 +6831,60 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, struct ifnet *ifp = ic->ic_ifp; struct ath_softc *sc = ifp->if_softc; struct ath_buf *bf; + int error; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) { DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__, (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ? "!running" : "invalid"); - sc->sc_stats.ast_tx_raw_fail++; - ieee80211_free_node(ni); m_freem(m); - return ENETDOWN; + error = ENETDOWN; + goto bad; } /* * Grab a TX buffer and associated resources. */ bf = ath_getbuf(sc); if (bf == NULL) { - /* NB: ath_getbuf handles stat+msg */ - ieee80211_free_node(ni); + sc->sc_stats.ast_tx_nobuf++; m_freem(m); - return ENOBUFS; + error = ENOBUFS; + goto bad; } - ifp->if_opackets++; - sc->sc_stats.ast_tx_raw++; - if (params == NULL) { /* * Legacy path; interpret frame contents to decide * precisely how to send the frame. */ - if (ath_tx_start(sc, ni, bf, m)) - goto bad; + if (ath_tx_start(sc, ni, bf, m)) { + error = EIO; /* XXX */ + goto bad2; + } } else { /* * Caller supplied explicit parameters to use in * sending the frame. */ - if (ath_tx_raw_start(sc, ni, bf, m, params)) - goto bad; + if (ath_tx_raw_start(sc, ni, bf, m, params)) { + error = EIO; /* XXX */ + goto bad2; + } } sc->sc_wd_timer = 5; + ifp->if_opackets++; + sc->sc_stats.ast_tx_raw++; return 0; -bad: - ifp->if_oerrors++; +bad2: ATH_TXBUF_LOCK(sc); STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); ATH_TXBUF_UNLOCK(sc); +bad: + ifp->if_oerrors++; + sc->sc_stats.ast_tx_raw_fail++; ieee80211_free_node(ni); - return EIO; /* XXX */ + return error; } /* diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index dba7a7a..327b736 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -1771,10 +1771,12 @@ static int bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct bwi_vap *bvp = BWI_VAP(vap); - struct ifnet *ifp = vap->iv_ic->ic_ifp; + struct ieee80211com *ic= vap->iv_ic; + struct ifnet *ifp = ic->ic_ifp; + enum ieee80211_state ostate = vap->iv_state; struct bwi_softc *sc = ifp->if_softc; struct bwi_mac *mac; - struct ieee80211_node *ni; + struct ieee80211_node *ni = vap->iv_bss; int error; BWI_LOCK(sc); @@ -1790,11 +1792,25 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (error != 0) goto back; + /* + * Clear the BSSID when we stop a STA + */ + if (vap->iv_opmode == IEEE80211_M_STA) { + if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) { + /* + * Clear out the BSSID. If we reassociate to + * the same AP, this will reinialize things + * correctly... + */ + if (ic->ic_opmode == IEEE80211_M_STA && + !(sc->sc_flags & BWI_F_STOP)) + bwi_set_bssid(sc, bwi_zero_addr); + } + } + if (vap->iv_opmode == IEEE80211_M_MONITOR) { /* Nothing to do */ } else if (nstate == IEEE80211_S_RUN) { - ni = vap->iv_bss; - bwi_set_bssid(sc, vap->iv_bss->ni_bssid); KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, @@ -1814,8 +1830,6 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc); - } else { - bwi_set_bssid(sc, bwi_zero_addr); } back: BWI_UNLOCK(sc); diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 71a6b23..d191d38 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -2727,31 +2727,7 @@ ndis_getstate_80211(sc) if (rval) device_printf (sc->ndis_dev, "get link speed failed: %d\n", rval); - - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { - ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B]; - for (i = 0; i < ni->ni_rates.rs_nrates; i++) { - if ((ni->ni_rates.rs_rates[i] & - IEEE80211_RATE_VAL) == arg / 5000) - break; - } - } - - if (i == ni->ni_rates.rs_nrates && - isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { - ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G]; - for (i = 0; i < ni->ni_rates.rs_nrates; i++) { - if ((ni->ni_rates.rs_rates[i] & - IEEE80211_RATE_VAL) == arg / 5000) - break; - } - } - - if (i == ni->ni_rates.rs_nrates) - device_printf(sc->ndis_dev, "no matching rate for: %d\n", - arg / 5000); - else - ni->ni_txrate = i; + ni->ni_txrate = arg / 5000; if (ic->ic_caps & IEEE80211_C_PMGT) { len = sizeof(arg); diff --git a/sys/dev/iir/iir.c b/sys/dev/iir/iir.c index cbcb449..f5f6d7e 100644 --- a/sys/dev/iir/iir.c +++ b/sys/dev/iir/iir.c @@ -67,9 +67,6 @@ __FBSDID("$FreeBSD$"); #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_message.h> -#include <vm/vm.h> -#include <vm/pmap.h> - #include <dev/iir/iir.h> MALLOC_DEFINE(M_GDTBUF, "iirbuf", "iir driver buffer"); diff --git a/sys/dev/iir/iir_ctrl.c b/sys/dev/iir/iir_ctrl.c index 6546f07..51ef043 100644 --- a/sys/dev/iir/iir_ctrl.c +++ b/sys/dev/iir/iir_ctrl.c @@ -52,10 +52,6 @@ __FBSDID("$FreeBSD$"); #include <sys/stat.h> #include <sys/disklabel.h> #include <machine/bus.h> -#include <vm/vm.h> -#include <vm/vm_kern.h> -#include <vm/vm_extern.h> -#include <vm/pmap.h> #include <dev/iir/iir.h> diff --git a/sys/dev/ksyms/ksyms.c b/sys/dev/ksyms/ksyms.c index f725f06..cb0f967 100644 --- a/sys/dev/ksyms/ksyms.c +++ b/sys/dev/ksyms/ksyms.c @@ -552,7 +552,7 @@ ksyms_read(struct cdev *dev, struct uio *uio, int flags __unused) /* ARGSUSED */ static int ksyms_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int32_t flag __unused, - d_thread_t *td __unused) + struct thread *td __unused) { int error = 0; struct ksyms_softc *sc; diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c index 9f9b986..f0d159b 100644 --- a/sys/dev/mii/e1000phy.c +++ b/sys/dev/mii/e1000phy.c @@ -238,21 +238,37 @@ e1000phy_reset(struct mii_softc *sc) } PHY_WRITE(sc, E1000_SCR, reg); - if (esc->mii_model == MII_MODEL_MARVELL_E1116) { + if (esc->mii_model == MII_MODEL_MARVELL_E1116 || + esc->mii_model == MII_MODEL_MARVELL_E1149) { + page = PHY_READ(sc, E1000_EADR); + /* Select page 2, MAC specific control register. */ PHY_WRITE(sc, E1000_EADR, 2); reg = PHY_READ(sc, E1000_SCR); reg |= E1000_SCR_RGMII_POWER_UP; PHY_WRITE(sc, E1000_SCR, reg); - PHY_WRITE(sc, E1000_EADR, 0); + PHY_WRITE(sc, E1000_EADR, page); } } switch (MII_MODEL(esc->mii_model)) { case MII_MODEL_MARVELL_E3082: case MII_MODEL_MARVELL_E1112: - case MII_MODEL_MARVELL_E1116: case MII_MODEL_MARVELL_E1118: + break; + case MII_MODEL_MARVELL_E1116: case MII_MODEL_MARVELL_E1149: + page = PHY_READ(sc, E1000_EADR); + /* Select page 3, LED control register. */ + PHY_WRITE(sc, E1000_EADR, 3); + PHY_WRITE(sc, E1000_SCR, + E1000_SCR_LED_LOS(1) | /* Link/Act */ + E1000_SCR_LED_INIT(8) | /* 10Mbps */ + E1000_SCR_LED_STAT1(7) | /* 100Mbps */ + E1000_SCR_LED_STAT0(7)); /* 1000Mbps */ + /* Set blink rate. */ + PHY_WRITE(sc, E1000_IER, E1000_PULSE_DUR(E1000_PULSE_170MS) | + E1000_BLINK_RATE(E1000_BLINK_84MS)); + PHY_WRITE(sc, E1000_EADR, page); break; case MII_MODEL_MARVELL_E3016: /* LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED. */ diff --git a/sys/dev/mii/e1000phyreg.h b/sys/dev/mii/e1000phyreg.h index 0b72224..41b9c09 100644 --- a/sys/dev/mii/e1000phyreg.h +++ b/sys/dev/mii/e1000phyreg.h @@ -256,9 +256,19 @@ /* 88E1116 page 0 */ #define E1000_SCR_POWER_DOWN 0x0004 -/* 88E1116 page 2 */ +/* 88E1116, 88E1149 page 2 */ #define E1000_SCR_RGMII_POWER_UP 0x0008 +/* 88E1116, 88E1149 page 3 */ +#define E1000_SCR_LED_STAT0_MASK 0x000F +#define E1000_SCR_LED_STAT1_MASK 0x00F0 +#define E1000_SCR_LED_INIT_MASK 0x0F00 +#define E1000_SCR_LED_LOS_MASK 0xF000 +#define E1000_SCR_LED_STAT0(x) ((x) & E1000_SCR_LED_STAT0_MASK) +#define E1000_SCR_LED_STAT1(x) ((x) & E1000_SCR_LED_STAT1_MASK) +#define E1000_SCR_LED_INIT(x) ((x) & E1000_SCR_LED_INIT_MASK) +#define E1000_SCR_LED_LOS(x) ((x) & E1000_SCR_LED_LOS_MASK) + #define E1000_SSR 0x11 /* special status register */ #define E1000_SSR_JABBER 0x0001 #define E1000_SSR_REV_POLARITY 0x0002 @@ -286,6 +296,26 @@ #define E1000_IER_SPEED_CHANGED 0x4000 #define E1000_IER_AUTO_NEG_ERR 0x8000 +/* 88E1116, 88E1149 page 3, LED timer control. */ +#define E1000_PULSE_MASK 0x7000 +#define E1000_PULSE_NO_STR 0 /* no pulse stretching */ +#define E1000_PULSE_21MS 1 /* 21 ms to 42 ms */ +#define E1000_PULSE_42MS 2 /* 42 ms to 84 ms */ +#define E1000_PULSE_84MS 3 /* 84 ms to 170 ms */ +#define E1000_PULSE_170MS 4 /* 170 ms to 340 ms */ +#define E1000_PULSE_340MS 5 /* 340 ms to 670 ms */ +#define E1000_PULSE_670MS 6 /* 670 ms to 1300 ms */ +#define E1000_PULSE_1300MS 7 /* 1300 ms to 2700 ms */ +#define E1000_PULSE_DUR(x) ((x) & E1000_PULSE_MASK) + +#define E1000_BLINK_MASK 0x0700 +#define E1000_BLINK_42MS 0 /* 42 ms */ +#define E1000_BLINK_84MS 1 /* 84 ms */ +#define E1000_BLINK_170MS 2 /* 170 ms */ +#define E1000_BLINK_340MS 3 /* 340 ms */ +#define E1000_BLINK_670MS 4 /* 670 ms */ +#define E1000_BLINK_RATE(x) ((x) & E1000_BLINK_MASK) + #define E1000_ISR 0x13 /* interrupt status reg */ #define E1000_ISR_JABBER 0x0001 #define E1000_ISR_POLARITY_CHANGE 0x0002 diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index 93575cf..73d5232 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -203,8 +203,6 @@ static struct msk_product { "Marvell Yukon 88E8040T Fast Ethernet" }, { VENDORID_MARVELL, DEVICEID_MRVL_8048, "Marvell Yukon 88E8048 Fast Ethernet" }, - { VENDORID_MARVELL, DEVICEID_MRVL_8070, - "Marvell Yukon 88E8070 Fast Ethernet" }, { VENDORID_MARVELL, DEVICEID_MRVL_4361, "Marvell Yukon 88E8050 Gigabit Ethernet" }, { VENDORID_MARVELL, DEVICEID_MRVL_4360, @@ -215,8 +213,14 @@ static struct msk_product { "Marvell Yukon 88E8055 Gigabit Ethernet" }, { VENDORID_MARVELL, DEVICEID_MRVL_4364, "Marvell Yukon 88E8056 Gigabit Ethernet" }, + { VENDORID_MARVELL, DEVICEID_MRVL_4365, + "Marvell Yukon 88E8070 Gigabit Ethernet" }, { VENDORID_MARVELL, DEVICEID_MRVL_436A, "Marvell Yukon 88E8058 Gigabit Ethernet" }, + { VENDORID_MARVELL, DEVICEID_MRVL_436B, + "Marvell Yukon 88E8071 Gigabit Ethernet" }, + { VENDORID_MARVELL, DEVICEID_MRVL_436C, + "Marvell Yukon 88E8072 Gigabit Ethernet" }, { VENDORID_DLINK, DEVICEID_DLINK_DGE550SX, "D-Link 550SX Gigabit Ethernet" }, { VENDORID_DLINK, DEVICEID_DLINK_DGE560T, @@ -226,7 +230,7 @@ static struct msk_product { static const char *model_name[] = { "Yukon XL", "Yukon EC Ultra", - "Yukon Unknown", + "Yukon EX", "Yukon EC", "Yukon FE", "Yukon FE+" @@ -258,8 +262,8 @@ static void msk_intr_hwerr(struct msk_softc *); #ifndef __NO_STRICT_ALIGNMENT static __inline void msk_fixup_rx(struct mbuf *); #endif -static void msk_rxeof(struct msk_if_softc *, uint32_t, int); -static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, int); +static void msk_rxeof(struct msk_if_softc *, uint32_t, uint32_t, int); +static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, uint32_t, int); static void msk_txeof(struct msk_if_softc *, int); static int msk_encap(struct msk_if_softc *, struct mbuf **); static void msk_tx_task(void *, int); @@ -267,6 +271,7 @@ static void msk_start(struct ifnet *); static int msk_ioctl(struct ifnet *, u_long, caddr_t); static void msk_set_prefetch(struct msk_softc *, int, bus_addr_t, uint32_t); static void msk_set_rambuffer(struct msk_if_softc *); +static void msk_set_tx_stfwd(struct msk_if_softc *); static void msk_init(void *); static void msk_init_locked(struct msk_if_softc *); static void msk_stop(struct msk_if_softc *); @@ -991,12 +996,17 @@ msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data) else ifp->if_hwassist &= ~MSK_CSUM_FEATURES; } + if ((mask & IFCAP_RXCSUM) != 0 && + (IFCAP_RXCSUM & ifp->if_capabilities) != 0) + ifp->if_capenable ^= IFCAP_RXCSUM; if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) { ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; msk_setvlan(sc_if, ifp); } - + if ((mask & IFCAP_VLAN_HWCSUM) != 0 && + (IFCAP_VLAN_HWCSUM & ifp->if_capabilities) != 0) + ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; if ((mask & IFCAP_TSO4) != 0 && (IFCAP_TSO4 & ifp->if_capabilities) != 0) { ifp->if_capenable ^= IFCAP_TSO4; @@ -1116,16 +1126,19 @@ msk_phy_power(struct msk_softc *sc, int mode) val = pci_read_config(sc->msk_dev, PCI_OUR_REG_1, 4); val &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); - switch (sc->msk_hw_id) { - case CHIP_ID_YUKON_XL: + if (sc->msk_hw_id == CHIP_ID_YUKON_XL) { if (sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { /* Deassert Low Power for 1st PHY. */ val |= PCI_Y2_PHY1_COMA; if (sc->msk_num_port > 1) val |= PCI_Y2_PHY2_COMA; } - break; + } + /* Release PHY from PowerDown/COMA mode. */ + pci_write_config(sc->msk_dev, PCI_OUR_REG_1, val, 4); + switch (sc->msk_hw_id) { case CHIP_ID_YUKON_EC_U: + case CHIP_ID_YUKON_EX: case CHIP_ID_YUKON_FE_P: CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_OFF); @@ -1136,14 +1149,22 @@ msk_phy_power(struct msk_softc *sc, int mode) PCI_ASPM_INT_FIFO_EMPTY|PCI_ASPM_CLKRUN_REQUEST); /* Set all bits to 0 except bits 15..12. */ pci_write_config(sc->msk_dev, PCI_OUR_REG_4, our, 4); - /* Set to default value. */ - pci_write_config(sc->msk_dev, PCI_OUR_REG_5, 0, 4); + our = pci_read_config(sc->msk_dev, PCI_OUR_REG_5, 4); + our &= PCI_CTL_TIM_VMAIN_AV_MSK; + pci_write_config(sc->msk_dev, PCI_OUR_REG_5, our, 4); + pci_write_config(sc->msk_dev, PCI_CFG_REG_1, 0, 4); + /* + * Disable status race, workaround for + * Yukon EC Ultra & Yukon EX. + */ + val = CSR_READ_4(sc, B2_GP_IO); + val |= GLB_GPIO_STAT_RACE_DIS; + CSR_WRITE_4(sc, B2_GP_IO, val); + CSR_READ_4(sc, B2_GP_IO); break; default: break; } - /* Release PHY from PowerDown/COMA mode. */ - pci_write_config(sc->msk_dev, PCI_OUR_REG_1, val, 4); for (i = 0; i < sc->msk_num_port; i++) { CSR_WRITE_2(sc, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET); @@ -1194,10 +1215,18 @@ mskc_reset(struct msk_softc *sc) CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); /* Disable ASF. */ - if (sc->msk_hw_id < CHIP_ID_YUKON_XL) { - CSR_WRITE_4(sc, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); - CSR_WRITE_2(sc, B0_CTST, Y2_ASF_DISABLE); - } + if (sc->msk_hw_id == CHIP_ID_YUKON_EX) { + status = CSR_READ_2(sc, B28_Y2_ASF_HCU_CCSR); + /* Clear AHB bridge & microcontroller reset. */ + status &= ~(Y2_ASF_HCU_CCSR_AHB_RST | + Y2_ASF_HCU_CCSR_CPU_RST_MODE); + /* Clear ASF microcontroller state. */ + status &= ~ Y2_ASF_HCU_CCSR_UC_STATE_MSK; + CSR_WRITE_2(sc, B28_Y2_ASF_HCU_CCSR, status); + } else + CSR_WRITE_1(sc, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); + CSR_WRITE_2(sc, B0_CTST, Y2_ASF_DISABLE); + /* * Since we disabled ASF, S/W reset is required for Power Management. */ @@ -1249,6 +1278,10 @@ mskc_reset(struct msk_softc *sc) CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_SET); CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_CLR); CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_F_LOOPB_OFF); + if (sc->msk_hw_id == CHIP_ID_YUKON_EX) + CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), + GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON | + GMC_BYP_RETR_ON); } CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); @@ -1469,6 +1502,13 @@ msk_attach(device_t dev) * make Rx checksum offload work on Yukon II hardware. */ ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_TSO4; + /* + * Enable Rx checksum offloading if controller support new + * descriptor format. + */ + if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0 && + (sc_if->msk_flags & MSK_FLAG_NORX_CSUM) == 0) + ifp->if_capabilities |= IFCAP_RXCSUM; ifp->if_hwassist = MSK_CSUM_FEATURES | CSUM_TSO; ifp->if_capenable = ifp->if_capabilities; ifp->if_ioctl = msk_ioctl; @@ -1512,6 +1552,13 @@ msk_attach(device_t dev) * for VLAN interface. */ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; + /* + * Enable Rx checksum offloading for VLAN taggedd frames + * if controller support new descriptor format. + */ + if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0 && + (sc_if->msk_flags & MSK_FLAG_NORX_CSUM) == 0) + ifp->if_capabilities |= IFCAP_VLAN_HWCSUM; } ifp->if_capenable = ifp->if_capabilities; @@ -1651,13 +1698,32 @@ mskc_attach(device_t dev) sc->msk_clock = 125; /* 125 Mhz */ sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_JUMBO_NOCSUM; break; + case CHIP_ID_YUKON_EX: + sc->msk_clock = 125; /* 125 Mhz */ + sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_DESCV2 | + MSK_FLAG_AUTOTX_CSUM; + /* + * Yukon Extreme seems to have silicon bug for + * automatic Tx checksum calculation capability. + */ + if (sc->msk_hw_rev == CHIP_REV_YU_EX_B0) + sc->msk_pflags &= ~MSK_FLAG_AUTOTX_CSUM; + /* + * Yukon Extreme A0 could not use store-and-forward + * for jumbo frames, so disable Tx checksum + * offloading for jumbo frames. + */ + if (sc->msk_hw_rev == CHIP_REV_YU_EX_A0) + sc->msk_pflags |= MSK_FLAG_JUMBO_NOCSUM; + break; case CHIP_ID_YUKON_FE: sc->msk_clock = 100; /* 100 Mhz */ sc->msk_pflags |= MSK_FLAG_FASTETHER; break; case CHIP_ID_YUKON_FE_P: sc->msk_clock = 50; /* 50 Mhz */ - sc->msk_pflags |= MSK_FLAG_FASTETHER | MSK_FLAG_DESCV2; + sc->msk_pflags |= MSK_FLAG_FASTETHER | MSK_FLAG_DESCV2 | + MSK_FLAG_AUTOTX_CSUM; if (sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) { /* * XXX @@ -1669,7 +1735,8 @@ mskc_attach(device_t dev) * Just pass received frames to upper stack with * minimal test and let upper stack handle them. */ - sc->msk_pflags |= MSK_FLAG_NOHWVLAN | MSK_FLAG_NORXCHK; + sc->msk_pflags |= MSK_FLAG_NOHWVLAN | + MSK_FLAG_NORXCHK | MSK_FLAG_NORX_CSUM; } break; case CHIP_ID_YUKON_XL: @@ -2450,8 +2517,10 @@ msk_encap(struct msk_if_softc *sc_if, struct mbuf **m_head) tcp_offset = offset = 0; m = *m_head; - if ((sc_if->msk_flags & MSK_FLAG_DESCV2) == 0 && - (m->m_pkthdr.csum_flags & (MSK_CSUM_FEATURES | CSUM_TSO)) != 0) { + if (((sc_if->msk_flags & MSK_FLAG_AUTOTX_CSUM) == 0 && + (m->m_pkthdr.csum_flags & MSK_CSUM_FEATURES) != 0) || + ((sc_if->msk_flags & MSK_FLAG_DESCV2) == 0 && + (m->m_pkthdr.csum_flags & CSUM_TSO) != 0)) { /* * Since mbuf has no protocol specific structure information * in it we have to inspect protocol information here to @@ -2510,9 +2579,12 @@ msk_encap(struct msk_if_softc *sc_if, struct mbuf **m_head) * resort to S/W checksum routine when we encounter short * TCP frames. * Short UDP packets appear to be handled correctly by - * Yukon II. + * Yukon II. Also I assume this bug does not happen on + * controllers that use newer descriptor format or + * automatic Tx checksum calaulcation. */ - if (m->m_pkthdr.len < MSK_MIN_FRAMELEN && + if ((sc_if->msk_flags & MSK_FLAG_AUTOTX_CSUM) == 0 && + (m->m_pkthdr.len < MSK_MIN_FRAMELEN) && (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) { m = m_pullup(m, offset + sizeof(struct tcphdr)); if (m == NULL) { @@ -2613,7 +2685,7 @@ msk_encap(struct msk_if_softc *sc_if, struct mbuf **m_head) } /* Check if we have to handle checksum offload. */ if (tso == 0 && (m->m_pkthdr.csum_flags & MSK_CSUM_FEATURES) != 0) { - if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0) + if ((sc_if->msk_flags & MSK_FLAG_AUTOTX_CSUM) != 0) control |= CALSUM; else { tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; @@ -2895,7 +2967,8 @@ msk_fixup_rx(struct mbuf *m) #endif static void -msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) +msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, uint32_t control, + int len) { struct mbuf *m; struct ifnet *ifp; @@ -2947,6 +3020,18 @@ msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) msk_fixup_rx(m); #endif ifp->if_ipackets++; + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 && + (control & (CSS_IPV4 | CSS_IPFRAG)) == CSS_IPV4) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((control & CSS_IPV4_CSUM_OK) != 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + if ((control & (CSS_TCP | CSS_UDP)) != 0 && + (control & (CSS_TCPUDP_CSUM_OK)) != 0) { + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } /* Check for VLAN tagged packets. */ if ((status & GMR_FS_VLAN) != 0 && (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { @@ -2963,7 +3048,8 @@ msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) } static void -msk_jumbo_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) +msk_jumbo_rxeof(struct msk_if_softc *sc_if, uint32_t status, uint32_t control, + int len) { struct mbuf *m; struct ifnet *ifp; @@ -3004,6 +3090,18 @@ msk_jumbo_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) msk_fixup_rx(m); #endif ifp->if_ipackets++; + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 && + (control & (CSS_IPV4 | CSS_IPFRAG)) == CSS_IPV4) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((control & CSS_IPV4_CSUM_OK) != 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + if ((control & (CSS_TCP | CSS_UDP)) != 0 && + (control & (CSS_TCPUDP_CSUM_OK)) != 0) { + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } /* Check for VLAN tagged packets. */ if ((status & GMR_FS_VLAN) != 0 && (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { @@ -3332,9 +3430,9 @@ msk_handle_events(struct msk_softc *sc) case OP_RXSTAT: if (sc_if->msk_framesize > (MCLBYTES - MSK_RX_BUF_ALIGN)) - msk_jumbo_rxeof(sc_if, status, len); + msk_jumbo_rxeof(sc_if, status, control, len); else - msk_rxeof(sc_if, status, len); + msk_rxeof(sc_if, status, control, len); rxprog++; /* * Because there is no way to sync single Rx LE @@ -3542,6 +3640,48 @@ done: } static void +msk_set_tx_stfwd(struct msk_if_softc *sc_if) +{ + struct msk_softc *sc; + struct ifnet *ifp; + + ifp = sc_if->msk_ifp; + sc = sc_if->msk_softc; + switch (sc->msk_hw_id) { + case CHIP_ID_YUKON_EX: + if (sc->msk_hw_rev == CHIP_REV_YU_EX_A0) + goto yukon_ex_workaround; + if (ifp->if_mtu > ETHERMTU) + CSR_WRITE_4(sc, + MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_ENA); + else + CSR_WRITE_4(sc, + MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); + break; + default: +yukon_ex_workaround: + if (ifp->if_mtu > ETHERMTU) { + /* Set Tx GMAC FIFO Almost Empty Threshold. */ + CSR_WRITE_4(sc, + MR_ADDR(sc_if->msk_port, TX_GMF_AE_THR), + MSK_ECU_JUMBO_WM << 16 | MSK_ECU_AE_THR); + /* Disable Store & Forward mode for Tx. */ + CSR_WRITE_4(sc, + MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); + } else { + /* Enable Store & Forward mode for Tx. */ + CSR_WRITE_4(sc, + MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); + } + break; + } +} + +static void msk_init(void *xsc) { struct msk_if_softc *sc_if = xsc; @@ -3590,6 +3730,10 @@ msk_init_locked(struct msk_if_softc *sc_if) CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_SET); CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_CLR); CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_F_LOOPB_OFF); + if (sc->msk_hw_id == CHIP_ID_YUKON_EX) + CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), + GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON | + GMC_BYP_RETR_ON); /* * Initialize GMAC first such that speed/duplex/flow-control @@ -3642,7 +3786,8 @@ msk_init_locked(struct msk_if_softc *sc_if) CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_SET); CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_CLR); reg = GMF_OPER_ON | GMF_RX_F_FL_ON; - if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P) + if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P || + sc->msk_hw_id == CHIP_ID_YUKON_EX) reg |= GMF_RX_OVER_ON; CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), reg); @@ -3678,20 +3823,8 @@ msk_init_locked(struct msk_if_softc *sc_if) MSK_ECU_LLPP); CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR), MSK_ECU_ULPP); - if (ifp->if_mtu > ETHERMTU) { - /* - * Set Tx GMAC FIFO Almost Empty Threshold. - */ - CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_AE_THR), - MSK_ECU_JUMBO_WM << 16 | MSK_ECU_AE_THR); - /* Disable Store & Forward mode for Tx. */ - CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); - } else { - /* Enable Store & Forward mode for Tx. */ - CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); - } + /* Configure store-and-forward for Tx. */ + msk_set_tx_stfwd(sc_if); } if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P && @@ -3722,10 +3855,23 @@ msk_init_locked(struct msk_if_softc *sc_if) CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_OPER_INIT); CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_FIFO_OP_ON); CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_WM), MSK_BMU_TX_WM); - if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U && - sc->msk_hw_rev == CHIP_REV_YU_EC_U_A0) { - /* Fix for Yukon-EC Ultra: set BMU FIFO level */ - CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_AL), MSK_ECU_TXFF_LEV); + switch (sc->msk_hw_id) { + case CHIP_ID_YUKON_EC_U: + if (sc->msk_hw_rev == CHIP_REV_YU_EC_U_A0) { + /* Fix for Yukon-EC Ultra: set BMU FIFO level */ + CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_AL), + MSK_ECU_TXFF_LEV); + } + break; + case CHIP_ID_YUKON_EX: + /* + * Yukon Extreme seems to have silicon bug for + * automatic Tx checksum calculation capability. + */ + if (sc->msk_hw_rev == CHIP_REV_YU_EX_B0) + CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_F), + F_TX_CHK_AUTO_OFF); + break; } /* Setup Rx Queue Bus Memory Interface. */ diff --git a/sys/dev/msk/if_mskreg.h b/sys/dev/msk/if_mskreg.h index 24a2376..d345b60 100644 --- a/sys/dev/msk/if_mskreg.h +++ b/sys/dev/msk/if_mskreg.h @@ -139,8 +139,10 @@ #define DEVICEID_MRVL_4362 0x4362 #define DEVICEID_MRVL_4363 0x4363 #define DEVICEID_MRVL_4364 0x4364 -#define DEVICEID_MRVL_8070 0x4365 +#define DEVICEID_MRVL_4365 0x4365 #define DEVICEID_MRVL_436A 0x436A +#define DEVICEID_MRVL_436B 0x436B +#define DEVICEID_MRVL_436C 0x436C /* * D-Link gigabit ethernet device ID @@ -225,6 +227,8 @@ #define PCI_OUR_REG_3 0x80 /* 32 bit Our Register 3 */ #define PCI_OUR_REG_4 0x84 /* 32 bit Our Register 4 */ #define PCI_OUR_REG_5 0x88 /* 32 bit Our Register 5 */ +#define PCI_CFG_REG_0 0x90 /* 32 bit Config Register 0 */ +#define PCI_CFG_REG_1 0x94 /* 32 bit Config Register 1 */ /* PCI Express Capability */ #define PEX_CAP_ID 0xe0 /* 8 bit PEX Capability ID */ @@ -325,6 +329,56 @@ #define PCI_CLK_GATE_PEX_UNIT_ENA BIT_1 /* Enable Gate PEX Unit Clock */ #define PCI_CLK_GATE_ROOT_COR_ENA BIT_0 /* Enable Gate Root Core Clock */ +/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */ + /* Bit 31..27: for A3 & later */ +#define PCI_CTL_DIV_CORE_CLK_ENA BIT_31 /* Divide Core Clock Enable */ +#define PCI_CTL_SRESET_VMAIN_AV BIT_30 /* Soft Reset for Vmain_av De-Glitch */ +#define PCI_CTL_BYPASS_VMAIN_AV BIT_29 /* Bypass En. for Vmain_av De-Glitch */ +#define PCI_CTL_TIM_VMAIN_AV1 BIT_28 /* Bit 28..27: Timer Vmain_av Mask */ +#define PCI_CTL_TIM_VMAIN_AV0 BIT_27 /* Bit 28..27: Timer Vmain_av Mask */ +#define PCI_CTL_TIM_VMAIN_AV_MSK (BIT_28 | BIT_27) + /* Bit 26..16: Release Clock on Event */ +#define PCI_REL_PCIE_RST_DE_ASS BIT_26 /* PCIe Reset De-Asserted */ +#define PCI_REL_GPHY_REC_PACKET BIT_25 /* GPHY Received Packet */ +#define PCI_REL_INT_FIFO_N_EMPTY BIT_24 /* Internal FIFO Not Empty */ +#define PCI_REL_MAIN_PWR_AVAIL BIT_23 /* Main Power Available */ +#define PCI_REL_CLKRUN_REQ_REL BIT_22 /* CLKRUN Request Release */ +#define PCI_REL_PCIE_RESET_ASS BIT_21 /* PCIe Reset Asserted */ +#define PCI_REL_PME_ASSERTED BIT_20 /* PME Asserted */ +#define PCI_REL_PCIE_EXIT_L1_ST BIT_19 /* PCIe Exit L1 State */ +#define PCI_REL_LOADER_NOT_FIN BIT_18 /* EPROM Loader Not Finished */ +#define PCI_REL_PCIE_RX_EX_IDLE BIT_17 /* PCIe Rx Exit Electrical Idle State */ +#define PCI_REL_GPHY_LINK_UP BIT_16 /* GPHY Link Up */ + /* Bit 10.. 0: Mask for Gate Clock */ +#define PCI_GAT_PCIE_RST_ASSERTED BIT_10 /* PCIe Reset Asserted */ +#define PCI_GAT_GPHY_N_REC_PACKET BIT_9 /* GPHY Not Received Packet */ +#define PCI_GAT_INT_FIFO_EMPTY BIT_8 /* Internal FIFO Empty */ +#define PCI_GAT_MAIN_PWR_N_AVAIL BIT_7 /* Main Power Not Available */ +#define PCI_GAT_CLKRUN_REQ_REL BIT_6 /* CLKRUN Not Requested */ +#define PCI_GAT_PCIE_RESET_ASS BIT_5 /* PCIe Reset Asserted */ +#define PCI_GAT_PME_DE_ASSERTED BIT_4 /* PME De-Asserted */ +#define PCI_GAT_PCIE_ENTER_L1_ST BIT_3 /* PCIe Enter L1 State */ +#define PCI_GAT_LOADER_FINISHED BIT_2 /* EPROM Loader Finished */ +#define PCI_GAT_PCIE_RX_EL_IDLE BIT_1 /* PCIe Rx Electrical Idle State */ +#define PCI_GAT_GPHY_LINK_DOWN BIT_0 /* GPHY Link Down */ + +/* PCI_CFG_REG_1 32 bit Config Register 1 */ +#define PCI_CF1_DIS_REL_EVT_RST BIT_24 /* Dis. Rel. Event during PCIE reset */ + /* Bit 23..21: Release Clock on Event */ +#define PCI_CF1_REL_LDR_NOT_FIN BIT_23 /* EEPROM Loader Not Finished */ +#define PCI_CF1_REL_VMAIN_AVLBL BIT_22 /* Vmain available */ +#define PCI_CF1_REL_PCIE_RESET BIT_21 /* PCI-E reset */ + /* Bit 20..18: Gate Clock on Event */ +#define PCI_CF1_GAT_LDR_NOT_FIN BIT_20 /* EEPROM Loader Finished */ +#define PCI_CF1_GAT_PCIE_RX_IDLE BIT_19 /* PCI-E Rx Electrical idle */ +#define PCI_CF1_GAT_PCIE_RESET BIT_18 /* PCI-E Reset */ +#define PCI_CF1_PRST_PHY_CLKREQ BIT_17 /* Enable PCI-E rst & PM2PHY gen. CLKREQ */ +#define PCI_CF1_PCIE_RST_CLKREQ BIT_16 /* Enable PCI-E rst generate CLKREQ */ + +#define PCI_CF1_ENA_CFG_LDR_DONE BIT_8 /* Enable core level Config loader done */ +#define PCI_CF1_ENA_TXBMU_RD_IDLE BIT_1 /* Enable TX BMU Read IDLE for ASPM */ +#define PCI_CF1_ENA_TXBMU_WR_IDLE BIT_0 /* Enable TX BMU Write IDLE for ASPM */ + /* PEX_DEV_CTRL 16 bit PEX Device Control (Yukon-2) */ #define PEX_DC_MAX_RRS_MSK (7<<12) /* Bit 14..12: Max. Read Request Size */ #define PEX_DC_EN_NO_SNOOP BIT_11 /* Enable No Snoop */ @@ -621,6 +675,7 @@ #define B28_Y2_SMB_CSD_REG 0x0e44 /* 32 bit ASF SMB Control/Status/Data */ #define B28_Y2_ASF_IRQ_V_BASE 0x0e60 /* 32 bit ASF IRQ Vector Base */ #define B28_Y2_ASF_STAT_CMD 0x0e68 /* 32 bit ASF Status and Command Reg */ +#define B28_Y2_ASF_HCU_CCSR 0x0e68 /* 32 bit ASF HCU CCSR (Yukon EX) */ #define B28_Y2_ASF_HOST_COM 0x0e6c /* 32 bit ASF Host Communication Reg */ #define B28_Y2_DATA_REG_1 0x0e70 /* 32 bit ASF/Host Data Register 1 */ #define B28_Y2_DATA_REG_2 0x0e74 /* 32 bit ASF/Host Data Register 2 */ @@ -830,6 +885,7 @@ #define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */ #define CHIP_ID_YUKON_XL 0xb3 /* Chip ID for YUKON-2 XL */ #define CHIP_ID_YUKON_EC_U 0xb4 /* Chip ID for YUKON-2 EC Ultra */ +#define CHIP_ID_YUKON_EX 0xb5 /* Chip ID for YUKON-2 Extreme */ #define CHIP_ID_YUKON_EC 0xb6 /* Chip ID for YUKON-2 EC */ #define CHIP_ID_YUKON_FE 0xb7 /* Chip ID for YUKON-2 FE */ #define CHIP_ID_YUKON_FE_P 0xb8 /* Chip ID for YUKON-2 FE+ */ @@ -848,6 +904,9 @@ #define CHIP_REV_YU_FE_P_A0 0 /* Chip Rev. for Yukon-2 FE+ A0 */ +#define CHIP_REV_YU_EX_A0 1 /* Chip Rev. for Yukon-2 EX A0 */ +#define CHIP_REV_YU_EX_B0 2 /* Chip Rev. for Yukon-2 EX B0 */ + /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ #define Y2_STATUS_LNK2_INAC BIT_7 /* Status Link 2 inactiv (0 = activ) */ #define Y2_CLK_GAT_LNK2_DIS BIT_6 /* Disable clock gating Link 2 */ @@ -912,6 +971,18 @@ #define TST_CFG_WRITE_ON BIT_1 /* Enable Config Reg WR */ #define TST_CFG_WRITE_OFF BIT_0 /* Disable Config Reg WR */ +/* B2_GP_IO */ +#define GLB_GPIO_CLK_DEB_ENA BIT_31 /* Clock Debug Enable */ +#define GLB_GPIO_CLK_DBG_MSK 0x3c000000 /* Clock Debug */ + +#define GLB_GPIO_INT_RST_D3_DIS BIT_15 /* Disable Internal Reset After D3 to D0 */ +#define GLB_GPIO_LED_PAD_SPEED_UP BIT_14 /* LED PAD Speed Up */ +#define GLB_GPIO_STAT_RACE_DIS BIT_13 /* Status Race Disable */ +#define GLB_GPIO_TEST_SEL_MSK 0x00001800 /* Testmode Select */ +#define GLB_GPIO_TEST_SEL_BASE BIT_11 +#define GLB_GPIO_RAND_ENA BIT_10 /* Random Enable */ +#define GLB_GPIO_RAND_BIT_1 BIT_9 /* Random Bit 1 */ + /* B2_I2C_CTRL 32 bit I2C HW Control Register */ #define I2C_FLAG BIT_31 /* Start read/write if WR */ #define I2C_ADDR (0x7fff<<16) /* Bit 30..16: Addr to be RD/WR */ @@ -1033,13 +1104,16 @@ /* Bit 10..0: same as for Rx */ /* Q_F 32 bit Flag Register */ -#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ -#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ -#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ -#define F_WM_REACHED BIT_25 /* Watermark reached */ -#define F_M_RX_RAM_DIS BIT_24 /* MAC Rx RAM Read Port disable */ -#define F_FIFO_LEVEL (0x1f<<16) /* Bit 23..16: # of Qwords in FIFO */ -#define F_WATER_MARK 0x0007ff /* Bit 10.. 0: Watermark */ +#define F_TX_CHK_AUTO_OFF BIT_31 /* Tx checksum auto-calc Off(Yukon EX)*/ +#define F_TX_CHK_AUTO_ON BIT_30 /* Tx checksum auto-calc On(Yukon EX)*/ +#define F_ALM_FULL BIT_28 /* Rx FIFO: almost full */ +#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ +#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ +#define F_WM_REACHED BIT_25 /* Watermark reached */ +#define F_M_RX_RAM_DIS BIT_24 /* MAC Rx RAM Read Port disable */ +#define F_FIFO_LEVEL (0x1f<<16) + /* Bit 23..16: # of Qwords in FIFO */ +#define F_WATER_MARK 0x0007ff/* Bit 10.. 0: Watermark */ /* Queue Prefetch Unit Offsets, use Y2_PREF_Q_ADDR() to address (Yukon-2 only)*/ /* PREF_UNIT_CTRL_REG 32 bit Prefetch Control register */ @@ -1927,6 +2001,28 @@ #define Y2_ASF_UC_STATE (3<<2) /* ASF uC State */ #define Y2_ASF_CLK_HALT 0 /* ASF system clock stopped */ +/* B28_Y2_ASF_HCU_CCSR 32bit CPU Control and Status Register (Yukon EX) */ +#define Y2_ASF_HCU_CCSR_SMBALERT_MONITOR BIT_27 /* SMBALERT pin monitor */ +#define Y2_ASF_HCU_CCSR_CPU_SLEEP BIT_26 /* CPU sleep status */ +#define Y2_ASF_HCU_CCSR_CS_TO BIT_25 /* Clock Stretching Timeout */ +#define Y2_ASF_HCU_CCSR_WDOG BIT_24 /* Watchdog Reset */ +#define Y2_ASF_HCU_CCSR_CLR_IRQ_HOST BIT_17 /* Clear IRQ_HOST */ +#define Y2_ASF_HCU_CCSR_SET_IRQ_HCU BIT_16 /* Set IRQ_HCU */ +#define Y2_ASF_HCU_CCSR_AHB_RST BIT_9 /* Reset AHB bridge */ +#define Y2_ASF_HCU_CCSR_CPU_RST_MODE BIT_8 /* CPU Reset Mode */ +#define Y2_ASF_HCU_CCSR_SET_SYNC_CPU BIT_5 +#define Y2_ASF_HCU_CCSR_CPU_CLK_DIVIDE1 BIT_4 +#define Y2_ASF_HCU_CCSR_CPU_CLK_DIVIDE0 BIT_3 +#define Y2_ASF_HCU_CCSR_CPU_CLK_DIVIDE_MSK (BIT_4 | BIT_3) /* CPU Clock Divide */ +#define Y2_ASF_HCU_CCSR_CPU_CLK_DIVIDE_BASE BIT_3 +#define Y2_ASF_HCU_CCSR_OS_PRSNT BIT_2 /* ASF OS Present */ + /* Microcontroller State */ +#define Y2_ASF_HCU_CCSR_UC_STATE_MSK 3 +#define Y2_ASF_HCU_CCSR_UC_STATE_BASE BIT_0 +#define Y2_ASF_HCU_CCSR_ASF_RESET 0 +#define Y2_ASF_HCU_CCSR_ASF_HALTED BIT_1 +#define Y2_ASF_HCU_CCSR_ASF_RUNNING BIT_0 + /* B28_Y2_ASF_HOST_COM 32 bit ASF Host Communication Reg */ /* This register is used by the ASF firmware */ #define Y2_ASF_CLR_ASFI BIT_1 /* Clear host IRQ */ @@ -1940,6 +2036,14 @@ #define SC_STAT_RST_SET BIT_0 /* Set Status Unit Reset */ /* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ +#define GMC_SEC_RST BIT_15 /* MAC SEC RST */ +#define GMC_SEC_RST_OFF BIT_14 /* MAC SEC RST Off */ +#define GMC_BYP_MACSECRX_ON BIT_13 /* Bypass MAC SEC RX */ +#define GMC_BYP_MACSECRX_OFF BIT_12 /* Bypass MAC SEC RX Off */ +#define GMC_BYP_MACSECTX_ON BIT_11 /* Bypass MAC SEC TX */ +#define GMC_BYP_MACSECTX_OFF BIT_10 /* Bypass MAC SEC TX Off */ +#define GMC_BYP_RETR_ON BIT_9 /* Bypass MAC retransmit FIFO On */ +#define GMC_BYP_RETR_OFF BIT_8 /* Bypass MAC retransmit FIFO Off */ #define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ #define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ #define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ @@ -2153,8 +2257,19 @@ struct msk_stat_desc { #define OP_PUTIDX 0x70000000 #define STLE_OP_MASK 0xff000000 +#define STLE_CSS_MASK 0x00ff0000 #define STLE_LEN_MASK 0x0000ffff +/* CSS defined in status LE(valid for descriptor V2 format). */ +#define CSS_TCPUDP_CSUM_OK 0x00800000 +#define CSS_UDP 0x00400000 +#define CSS_TCP 0x00200000 +#define CSS_IPFRAG 0x00100000 +#define CSS_IPV6 0x00080000 +#define CSS_IPV4_CSUM_OK 0x00040000 +#define CSS_IPV4 0x00020000 +#define CSS_PORT 0x00010000 + /* Descriptor Bit Definition */ /* TxCtrl Transmit Buffer Control Field */ /* RxCtrl Receive Buffer Control Field */ @@ -2400,8 +2515,10 @@ struct msk_if_softc { #define MSK_FLAG_JUMBO_NOCSUM 0x0010 #define MSK_FLAG_RAMBUF 0x0020 #define MSK_FLAG_DESCV2 0x0040 -#define MSK_FLAG_NOHWVLAN 0x0080 -#define MSK_FLAG_NORXCHK 0x0100 +#define MSK_FLAG_AUTOTX_CSUM 0x0080 +#define MSK_FLAG_NOHWVLAN 0x0100 +#define MSK_FLAG_NORXCHK 0x0200 +#define MSK_FLAG_NORX_CSUM 0x0400 #define MSK_FLAG_SUSPEND 0x2000 #define MSK_FLAG_DETACH 0x4000 #define MSK_FLAG_LINK 0x8000 diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index 22b5ce2..765b4d9 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -30,8 +30,6 @@ POSSIBILITY OF SUCH DAMAGE. #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#define IFNET_BUF_RING - #include <sys/param.h> #include <sys/systm.h> #include <sys/linker.h> @@ -68,9 +66,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/in_cksum.h> #include <machine/resource.h> -#ifdef IFNET_BUF_RING -#include <sys/buf_ring.h> -#endif #include <sys/bus.h> #include <sys/rman.h> #include <sys/smp.h> @@ -90,6 +85,9 @@ __FBSDID("$FreeBSD$"); #include <dev/mxge/mcp_gen_header.h> /*#define MXGE_FAKE_IFP*/ #include <dev/mxge/if_mxge_var.h> +#ifdef IFNET_BUF_RING +#include <sys/buf_ring.h> +#endif /* tunable params */ static int mxge_nvidia_ecrc_enable = 1; @@ -2200,6 +2198,7 @@ mxge_transmit_locked(struct mxge_slice_state *ss, struct mbuf *m) BPF_MTAP(ifp, m); /* give it to the nic */ mxge_encap(ss, m); + drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags); } else if ((err = drbr_enqueue(ifp, tx->br, m)) != 0) { return (err); } @@ -2656,11 +2655,6 @@ mxge_tx_done(struct mxge_slice_state *ss, uint32_t mcp_idx) /* mbuf and DMA map only attached to the first segment per-mbuf */ if (m != NULL) { -#ifdef IFNET_BUF_RING - ss->obytes += m->m_pkthdr.len; - if (m->m_flags & M_MCAST) - ss->omcasts++; -#endif ss->opackets++; tx->info[idx].m = NULL; map = tx->info[idx].map; @@ -3787,11 +3781,6 @@ mxge_update_stats(mxge_softc_t *sc) struct mxge_slice_state *ss; u_long ipackets = 0; u_long opackets = 0; -#ifdef IFNET_BUF_RING - u_long obytes = 0; - u_long omcasts = 0; - u_long odrops = 0; -#endif u_long oerrors = 0; int slice; @@ -3799,20 +3788,10 @@ mxge_update_stats(mxge_softc_t *sc) ss = &sc->ss[slice]; ipackets += ss->ipackets; opackets += ss->opackets; -#ifdef IFNET_BUF_RING - obytes += ss->obytes; - omcasts += ss->omcasts; - odrops += ss->tx.br->br_drops; -#endif oerrors += ss->oerrors; } sc->ifp->if_ipackets = ipackets; sc->ifp->if_opackets = opackets; -#ifdef IFNET_BUF_RING - sc->ifp->if_obytes = obytes; - sc->ifp->if_omcasts = omcasts; - sc->ifp->if_snd.ifq_drops = odrops; -#endif sc->ifp->if_oerrors = oerrors; } diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index b17faf2..8240b62 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -46,6 +46,10 @@ $FreeBSD$ #define MXGE_VIRT_JUMBOS 0 #endif +#if (__FreeBSD_version > 800082) +#define IFNET_BUF_RING 1 +#endif + #ifndef VLAN_CAPABILITIES #define VLAN_CAPABILITIES(ifp) #define mxge_vlans_active(sc) (sc)->ifp->if_nvlans @@ -192,8 +196,6 @@ struct mxge_slice_state { volatile uint32_t *irq_claim; u_long ipackets; u_long opackets; - u_long obytes; - u_long omcasts; u_long oerrors; int if_drv_flags; struct lro_head lro_active; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 49a272b..667072f 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <sys/rman.h> #include <machine/resource.h> +#include <machine/stdarg.h> #if defined(__i386__) || defined(__amd64__) #include <machine/intr_machdep.h> diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c index 4d42a04..07f603d 100644 --- a/sys/dev/puc/pucdata.c +++ b/sys/dev/puc/pucdata.c @@ -234,6 +234,17 @@ const struct puc_cfg puc_pci_devices[] = { }, /* + * IBM SurePOS 300 Series (481033H) serial ports + * Details can be found on the IBM RSS websites + */ + + { 0x1014, 0x0297, 0xffff, 0, + "IBM SurePOS 300 Series (481033H) serial ports", + DEFAULT_RCLK, + PUC_PORT_4S, 0x10, 4, 0 + }, + + /* * SIIG Boards. * * SIIG provides documentation for their boards at: diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 32826664..836cedf 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -822,7 +822,7 @@ detach: return (ENXIO); /* error */ } -int +static int ukbd_detach(device_t dev) { struct ukbd_softc *sc = device_get_softc(dev); @@ -1569,7 +1569,7 @@ static int ukbd_driver_load(module_t mod, int what, void *arg) { switch (what) { - case MOD_LOAD: + case MOD_LOAD: kbd_add_driver(&ukbd_kbd_driver); break; case MOD_UNLOAD: diff --git a/sys/dev/usb/usb_compat_linux.h b/sys/dev/usb/usb_compat_linux.h index 9066702..0dc815d 100644 --- a/sys/dev/usb/usb_compat_linux.h +++ b/sys/dev/usb/usb_compat_linux.h @@ -339,6 +339,6 @@ void usb_linux_register(void *arg); void usb_linux_deregister(void *arg); #define interface_to_usbdev(intf) (intf)->linux_udev -#define interface_to_bsddev(intf) (intf)->linux_udev->bsd_udev +#define interface_to_bsddev(intf) (intf)->linux_udev #endif /* _USB_COMPAT_LINUX_H */ diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index 138fc5c..1b1e986 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -88,9 +88,9 @@ static struct usb_pipe *usb2_dev_get_pipe(struct usb_device *, uint8_t, static void usb2_loc_fill(struct usb_fs_privdata *, struct usb_cdev_privdata *); static void usb2_close(void *); -static usb_error_t usb2_ref_device(struct usb_cdev_privdata *, int); -static usb_error_t usb2_usb_ref_device(struct usb_cdev_privdata *); -static void usb2_unref_device(struct usb_cdev_privdata *); +static usb_error_t usb2_ref_device(struct usb_cdev_privdata *, struct usb_cdev_refdata *, int); +static usb_error_t usb2_usb_ref_device(struct usb_cdev_privdata *, struct usb_cdev_refdata *); +static void usb2_unref_device(struct usb_cdev_privdata *, struct usb_cdev_refdata *); static d_open_t usb2_open; static d_ioctl_t usb2_ioctl; @@ -158,12 +158,16 @@ usb2_loc_fill(struct usb_fs_privdata* pd, struct usb_cdev_privdata *cpd) * Else: Failure. *------------------------------------------------------------------------*/ usb_error_t -usb2_ref_device(struct usb_cdev_privdata* cpd, int need_uref) +usb2_ref_device(struct usb_cdev_privdata *cpd, + struct usb_cdev_refdata *crd, int need_uref) { struct usb_fifo **ppf; struct usb_fifo *f; - DPRINTFN(2, "usb2_ref_device, cpd=%p need uref=%d\n", cpd, need_uref); + DPRINTFN(2, "cpd=%p need uref=%d\n", cpd, need_uref); + + /* clear all refs */ + memset(crd, 0, sizeof(*crd)); mtx_lock(&usb2_ref_lock); cpd->bus = devclass_get_softc(usb2_devclass_ptr, cpd->bus_index); @@ -183,7 +187,6 @@ usb2_ref_device(struct usb_cdev_privdata* cpd, int need_uref) if (need_uref) { DPRINTFN(2, "ref udev - needed\n"); cpd->udev->refcount++; - cpd->is_uref = 1; mtx_unlock(&usb2_ref_lock); @@ -194,82 +197,72 @@ usb2_ref_device(struct usb_cdev_privdata* cpd, int need_uref) sx_xlock(cpd->udev->default_sx + 1); mtx_lock(&usb2_ref_lock); + + /* + * Set "is_uref" after grabbing the default SX lock + */ + crd->is_uref = 1; } /* check if we are doing an open */ if (cpd->fflags == 0) { - /* set defaults */ - cpd->txfifo = NULL; - cpd->rxfifo = NULL; - cpd->is_write = 0; - cpd->is_read = 0; - cpd->is_usbfs = 0; + /* use zero defaults */ } else { - /* initialise "is_usbfs" flag */ - cpd->is_usbfs = 0; - /* check for write */ if (cpd->fflags & FWRITE) { ppf = cpd->udev->fifo; f = ppf[cpd->fifo_index + USB_FIFO_TX]; - cpd->txfifo = f; - cpd->is_write = 1; /* ref */ + crd->txfifo = f; + crd->is_write = 1; /* ref */ if (f == NULL || f->refcount == USB_FIFO_REF_MAX) goto error; if (f->curr_cpd != cpd) goto error; /* check if USB-FS is active */ if (f->fs_ep_max != 0) { - cpd->is_usbfs = 1; + crd->is_usbfs = 1; } - } else { - cpd->txfifo = NULL; - cpd->is_write = 0; /* no ref */ } /* check for read */ if (cpd->fflags & FREAD) { ppf = cpd->udev->fifo; f = ppf[cpd->fifo_index + USB_FIFO_RX]; - cpd->rxfifo = f; - cpd->is_read = 1; /* ref */ + crd->rxfifo = f; + crd->is_read = 1; /* ref */ if (f == NULL || f->refcount == USB_FIFO_REF_MAX) goto error; if (f->curr_cpd != cpd) goto error; /* check if USB-FS is active */ if (f->fs_ep_max != 0) { - cpd->is_usbfs = 1; + crd->is_usbfs = 1; } - } else { - cpd->rxfifo = NULL; - cpd->is_read = 0; /* no ref */ } } /* when everything is OK we increment the refcounts */ - if (cpd->is_write) { + if (crd->is_write) { DPRINTFN(2, "ref write\n"); - cpd->txfifo->refcount++; + crd->txfifo->refcount++; } - if (cpd->is_read) { + if (crd->is_read) { DPRINTFN(2, "ref read\n"); - cpd->rxfifo->refcount++; + crd->rxfifo->refcount++; } mtx_unlock(&usb2_ref_lock); - if (cpd->is_uref) { + if (crd->is_uref) { mtx_lock(&Giant); /* XXX */ } return (0); error: - if (cpd->is_uref) { + if (crd->is_uref) { sx_unlock(cpd->udev->default_sx + 1); if (--(cpd->udev->refcount) == 0) { usb2_cv_signal(cpd->udev->default_cv + 1); } - cpd->is_uref = 0; } mtx_unlock(&usb2_ref_lock); DPRINTFN(2, "fail\n"); @@ -287,21 +280,22 @@ error: * Else: Failure. *------------------------------------------------------------------------*/ static usb_error_t -usb2_usb_ref_device(struct usb_cdev_privdata *cpd) +usb2_usb_ref_device(struct usb_cdev_privdata *cpd, + struct usb_cdev_refdata *crd) { /* * Check if we already got an USB reference on this location: */ - if (cpd->is_uref) + if (crd->is_uref) return (0); /* success */ /* * To avoid deadlock at detach we need to drop the FIFO ref * and re-acquire a new ref! */ - usb2_unref_device(cpd); + usb2_unref_device(cpd, crd); - return (usb2_ref_device(cpd, 1 /* need uref */)); + return (usb2_ref_device(cpd, crd, 1 /* need uref */)); } /*------------------------------------------------------------------------* @@ -311,30 +305,34 @@ usb2_usb_ref_device(struct usb_cdev_privdata *cpd) * given USB device. *------------------------------------------------------------------------*/ void -usb2_unref_device(struct usb_cdev_privdata *cpd) +usb2_unref_device(struct usb_cdev_privdata *cpd, + struct usb_cdev_refdata *crd) { - if (cpd->is_uref) { + + DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref); + + if (crd->is_uref) { mtx_unlock(&Giant); /* XXX */ sx_unlock(cpd->udev->default_sx + 1); } mtx_lock(&usb2_ref_lock); - if (cpd->is_read) { - if (--(cpd->rxfifo->refcount) == 0) { - usb2_cv_signal(&cpd->rxfifo->cv_drain); + if (crd->is_read) { + if (--(crd->rxfifo->refcount) == 0) { + usb2_cv_signal(&crd->rxfifo->cv_drain); } - cpd->is_read = 0; + crd->is_read = 0; } - if (cpd->is_write) { - if (--(cpd->txfifo->refcount) == 0) { - usb2_cv_signal(&cpd->txfifo->cv_drain); + if (crd->is_write) { + if (--(crd->txfifo->refcount) == 0) { + usb2_cv_signal(&crd->txfifo->cv_drain); } - cpd->is_write = 0; + crd->is_write = 0; } - if (cpd->is_uref) { + if (crd->is_uref) { if (--(cpd->udev->refcount) == 0) { usb2_cv_signal(cpd->udev->default_cv + 1); } - cpd->is_uref = 0; + crd->is_uref = 0; } mtx_unlock(&usb2_ref_lock); } @@ -357,7 +355,8 @@ usb2_fifo_alloc(void) * usb2_fifo_create *------------------------------------------------------------------------*/ static int -usb2_fifo_create(struct usb_cdev_privdata *cpd) +usb2_fifo_create(struct usb_cdev_privdata *cpd, + struct usb_cdev_refdata *crd) { struct usb_device *udev = cpd->udev; struct usb_fifo *f; @@ -381,13 +380,13 @@ usb2_fifo_create(struct usb_cdev_privdata *cpd) f = udev->fifo[cpd->fifo_index + USB_FIFO_TX]; if (f == NULL) return (EINVAL); - cpd->txfifo = f; + crd->txfifo = f; } if (is_rx) { f = udev->fifo[cpd->fifo_index + USB_FIFO_RX]; if (f == NULL) return (EINVAL); - cpd->rxfifo = f; + crd->rxfifo = f; } return (0); } @@ -516,10 +515,10 @@ usb2_fifo_create(struct usb_cdev_privdata *cpd) mtx_unlock(&usb2_ref_lock); } if (is_tx) { - cpd->txfifo = udev->fifo[n + USB_FIFO_TX]; + crd->txfifo = udev->fifo[n + USB_FIFO_TX]; } if (is_rx) { - cpd->rxfifo = udev->fifo[n + USB_FIFO_RX]; + crd->rxfifo = udev->fifo[n + USB_FIFO_RX]; } /* fill out fifo index */ DPRINTFN(5, "fifo index = %d\n", n); @@ -806,6 +805,7 @@ static int usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td) { struct usb_fs_privdata* pd = (struct usb_fs_privdata*)dev->si_drv1; + struct usb_cdev_refdata refs; struct usb_cdev_privdata *cpd; int err, ep; @@ -822,7 +822,7 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td) ep = cpd->ep_addr = pd->ep_addr; usb2_loc_fill(pd, cpd); - err = usb2_ref_device(cpd, 1); + err = usb2_ref_device(cpd, &refs, 1); if (err) { DPRINTFN(2, "cannot ref device\n"); free(cpd, M_USBDEV); @@ -831,36 +831,36 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td) cpd->fflags = fflags; /* access mode for open lifetime */ /* create FIFOs, if any */ - err = usb2_fifo_create(cpd); + err = usb2_fifo_create(cpd, &refs); /* check for error */ if (err) { DPRINTFN(2, "cannot create fifo\n"); - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); free(cpd, M_USBDEV); return (err); } if (fflags & FREAD) { - err = usb2_fifo_open(cpd, cpd->rxfifo, fflags); + err = usb2_fifo_open(cpd, refs.rxfifo, fflags); if (err) { DPRINTFN(2, "read open failed\n"); - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); free(cpd, M_USBDEV); return (err); } } if (fflags & FWRITE) { - err = usb2_fifo_open(cpd, cpd->txfifo, fflags); + err = usb2_fifo_open(cpd, refs.txfifo, fflags); if (err) { DPRINTFN(2, "write open failed\n"); if (fflags & FREAD) { - usb2_fifo_close(cpd->rxfifo, fflags); + usb2_fifo_close(refs.rxfifo, fflags); } - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); free(cpd, M_USBDEV); return (err); } } - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); devfs_set_cdevpriv(cpd, usb2_close); return (0); @@ -872,24 +872,25 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td) static void usb2_close(void *arg) { + struct usb_cdev_refdata refs; struct usb_cdev_privdata *cpd = arg; int err; DPRINTFN(2, "cpd=%p\n", cpd); - err = usb2_ref_device(cpd, 1); + err = usb2_ref_device(cpd, &refs, 1); if (err) { free(cpd, M_USBDEV); return; } if (cpd->fflags & FREAD) { - usb2_fifo_close(cpd->rxfifo, cpd->fflags); + usb2_fifo_close(refs.rxfifo, cpd->fflags); } if (cpd->fflags & FWRITE) { - usb2_fifo_close(cpd->txfifo, cpd->fflags); + usb2_fifo_close(refs.txfifo, cpd->fflags); } - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); free(cpd, M_USBDEV); return; } @@ -988,6 +989,7 @@ usb2_ioctl_f_sub(struct usb_fifo *f, u_long cmd, void *addr, static int usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* td) { + struct usb_cdev_refdata refs; struct usb_cdev_privdata* cpd; struct usb_fifo *f; int fflags; @@ -1000,11 +1002,11 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* return (err); /* - * Performance optimistaion: We try to check for IOCTL's that + * Performance optimisation: We try to check for IOCTL's that * don't need the USB reference first. Then we grab the USB * reference if we need it! */ - err = usb2_ref_device(cpd, 0 /* no uref */ ); + err = usb2_ref_device(cpd, &refs, 0 /* no uref */ ); if (err) { return (ENXIO); } @@ -1014,11 +1016,11 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* err = ENOIOCTL; /* set default value */ if (fflags & FWRITE) { - f = cpd->txfifo; + f = refs.txfifo; err = usb2_ioctl_f_sub(f, cmd, addr, td); } if (fflags & FREAD) { - f = cpd->rxfifo; + f = refs.rxfifo; err = usb2_ioctl_f_sub(f, cmd, addr, td); } KASSERT(f != NULL, ("fifo not found")); @@ -1026,7 +1028,7 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* err = (f->methods->f_ioctl) (f, cmd, addr, fflags); DPRINTFN(2, "f_ioctl cmd 0x%lx = %d\n", cmd, err); if (err == ENOIOCTL) { - if (usb2_usb_ref_device(cpd)) { + if (usb2_usb_ref_device(cpd, &refs)) { err = ENXIO; goto done; } @@ -1038,7 +1040,7 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* err = ENOTTY; } done: - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); return (err); } @@ -1046,13 +1048,14 @@ done: static int usb2_poll(struct cdev* dev, int events, struct thread* td) { + struct usb_cdev_refdata refs; struct usb_cdev_privdata* cpd; struct usb_fifo *f; struct usb_mbuf *m; int fflags, revents; if (devfs_get_cdevpriv((void **)&cpd) != 0 || - usb2_ref_device(cpd, 0) != 0) + usb2_ref_device(cpd, &refs, 0) != 0) return (events & (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM)); @@ -1063,11 +1066,11 @@ usb2_poll(struct cdev* dev, int events, struct thread* td) if ((events & (POLLOUT | POLLWRNORM)) && (fflags & FWRITE)) { - f = cpd->txfifo; + f = refs.txfifo; mtx_lock(f->priv_mtx); - if (!cpd->is_usbfs) { + if (!refs.is_usbfs) { if (f->flag_iserror) { /* we got an error */ m = (void *)1; @@ -1102,11 +1105,11 @@ usb2_poll(struct cdev* dev, int events, struct thread* td) if ((events & (POLLIN | POLLRDNORM)) && (fflags & FREAD)) { - f = cpd->rxfifo; + f = refs.rxfifo; mtx_lock(f->priv_mtx); - if (!cpd->is_usbfs) { + if (!refs.is_usbfs) { if (f->flag_iserror) { /* we have and error */ m = (void *)1; @@ -1135,7 +1138,7 @@ usb2_poll(struct cdev* dev, int events, struct thread* td) f->flag_isselect = 1; selrecord(td, &f->selinfo); - if (!cpd->is_usbfs) { + if (!refs.is_usbfs) { /* start reading data */ (f->methods->f_start_read) (f); } @@ -1143,13 +1146,14 @@ usb2_poll(struct cdev* dev, int events, struct thread* td) mtx_unlock(f->priv_mtx); } - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); return (revents); } static int usb2_read(struct cdev *dev, struct uio *uio, int ioflag) { + struct usb_cdev_refdata refs; struct usb_cdev_privdata* cpd; struct usb_fifo *f; struct usb_mbuf *m; @@ -1163,15 +1167,16 @@ usb2_read(struct cdev *dev, struct uio *uio, int ioflag) if (err != 0) return (err); - err = usb2_ref_device(cpd, 0 /* no uref */ ); + err = usb2_ref_device(cpd, &refs, 0 /* no uref */ ); if (err) { return (ENXIO); } fflags = cpd->fflags; - f = cpd->rxfifo; + f = refs.rxfifo; if (f == NULL) { /* should not happen */ + usb2_unref_device(cpd, &refs); return (EPERM); } @@ -1185,7 +1190,7 @@ usb2_read(struct cdev *dev, struct uio *uio, int ioflag) goto done; } /* check if USB-FS interface is active */ - if (cpd->is_usbfs) { + if (refs.is_usbfs) { /* * The queue is used for events that should be * retrieved using the "USB_FS_COMPLETE" ioctl. @@ -1263,7 +1268,7 @@ usb2_read(struct cdev *dev, struct uio *uio, int ioflag) done: mtx_unlock(f->priv_mtx); - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); return (err); } @@ -1271,6 +1276,7 @@ done: static int usb2_write(struct cdev *dev, struct uio *uio, int ioflag) { + struct usb_cdev_refdata refs; struct usb_cdev_privdata* cpd; struct usb_fifo *f; struct usb_mbuf *m; @@ -1286,16 +1292,16 @@ usb2_write(struct cdev *dev, struct uio *uio, int ioflag) if (err != 0) return (err); - err = usb2_ref_device(cpd, 0 /* no uref */ ); + err = usb2_ref_device(cpd, &refs, 0 /* no uref */ ); if (err) { return (ENXIO); } fflags = cpd->fflags; - f = cpd->txfifo; + f = refs.txfifo; if (f == NULL) { /* should not happen */ - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); return (EPERM); } resid = uio->uio_resid; @@ -1308,7 +1314,7 @@ usb2_write(struct cdev *dev, struct uio *uio, int ioflag) goto done; } /* check if USB-FS interface is active */ - if (cpd->is_usbfs) { + if (refs.is_usbfs) { /* * The queue is used for events that should be * retrieved using the "USB_FS_COMPLETE" ioctl. @@ -1376,7 +1382,7 @@ usb2_write(struct cdev *dev, struct uio *uio, int ioflag) done: mtx_unlock(f->priv_mtx); - usb2_unref_device(cpd); + usb2_unref_device(cpd, &refs); return (err); } diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h index 3f21542..fb41e5a 100644 --- a/sys/dev/usb/usb_dev.h +++ b/sys/dev/usb/usb_dev.h @@ -88,13 +88,19 @@ struct usb_cdev_privdata { struct usb_bus *bus; struct usb_device *udev; struct usb_interface *iface; - struct usb_fifo *rxfifo; - struct usb_fifo *txfifo; int bus_index; /* bus index */ int dev_index; /* device index */ int ep_addr; /* endpoint address */ int fflags; uint8_t fifo_index; /* FIFO index */ +}; + +/* + * Private per-device and per-thread reference information + */ +struct usb_cdev_refdata { + struct usb_fifo *rxfifo; + struct usb_fifo *txfifo; uint8_t is_read; /* location has read access */ uint8_t is_write; /* location has write access */ uint8_t is_uref; /* USB refcount decr. needed */ diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c index 3e25655..bdf0a03 100644 --- a/sys/dev/usb/usb_request.c +++ b/sys/dev/usb/usb_request.c @@ -109,11 +109,11 @@ usb2_do_clear_stall_callback(struct usb_xfer *xfer) pipe_end = udev->pipes + udev->pipes_max; pipe_first = udev->pipes; to = udev->pipes_max; - if (pipe == NULL) { - pipe = pipe_first; - } + switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: + if (pipe == NULL) + goto tr_setup; /* device was unconfigured */ if (pipe->edesc && pipe->is_stalled) { pipe->toggle_next = 0; @@ -126,9 +126,10 @@ usb2_do_clear_stall_callback(struct usb_xfer *xfer) case USB_ST_SETUP: tr_setup: - if (pipe == pipe_end) { - pipe = pipe_first; - } + if (to == 0) + break; /* no pipes - nothing to do */ + if ((pipe < pipe_first) || (pipe >= pipe_end)) + pipe = pipe_first; /* pipe wrapped around */ if (pipe->edesc && pipe->is_stalled) { @@ -156,9 +157,8 @@ tr_setup: break; } pipe++; - if (--to) - goto tr_setup; - break; + to--; + goto tr_setup; default: if (xfer->error == USB_ERR_CANCELLED) { diff --git a/sys/gnu/fs/ext2fs/ext2_fs.h b/sys/gnu/fs/ext2fs/ext2_fs.h index c1d6ffd..8a4081e 100644 --- a/sys/gnu/fs/ext2fs/ext2_fs.h +++ b/sys/gnu/fs/ext2fs/ext2_fs.h @@ -52,6 +52,8 @@ #define umode_t mode_t #define loff_t off_t +#define cpu_to_le32(x) htole32(x) + /* * The second extended filesystem constants/structures */ @@ -87,12 +89,10 @@ #endif /* - * Special inodes numbers + * Special inode numbers */ #define EXT2_BAD_INO 1 /* Bad blocks inode */ #define EXT2_ROOT_INO 2 /* Root inode */ -#define EXT2_ACL_IDX_INO 3 /* ACL inode */ -#define EXT2_ACL_DATA_INO 4 /* ACL inode */ #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ @@ -104,17 +104,29 @@ */ #define EXT2_SUPER_MAGIC 0xEF53 +#ifdef __KERNEL__ +#include <linux/ext2_fs_sb.h> +static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} +#elif defined(_KERNEL) /* - * Maximal count of links to a file + * FreeBSD passes the pointer to the in-core struct with relevant + * fields to EXT2_SB macro when accessing superblock fields. */ -#define EXT2_LINK_MAX 32000 +#define EXT2_SB(sb) (sb) +#else +/* Assume that user mode programs are passing in an ext2fs superblock, not + * a kernel struct super_block. This will allow us to call the feature-test + * macros from user land. */ +#define EXT2_SB(sb) (sb) +#endif /* - * Note: under FreeBSD, the "user" versions of the following macros are - * used (and must be used) in most cases, because ((s)->u.ext2_sb.s_es is - * not accessible. This depends on __KERNEL__ not being defined for - * kernel builds under FreeBSD. + * Maximal count of links to a file */ +#define EXT2_LINK_MAX 32000 /* * Macro-instructions used to manage several block sizes @@ -122,23 +134,22 @@ #define EXT2_MIN_BLOCK_SIZE 1024 #define EXT2_MAX_BLOCK_SIZE 4096 #define EXT2_MIN_BLOCK_LOG_SIZE 10 -#if defined(__KERNEL__) || (defined(__FreeBSD__) && defined(_KERNEL)) +#if defined(__KERNEL__) || defined(_KERNEL) # define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) #else # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) #endif -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry)) #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) -#ifdef __KERNEL__ +#if defined(__KERNEL__) || defined(_KERNEL) # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) #else # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) #endif -#ifdef notyet -#ifdef __KERNEL__ -#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits) -#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size) -#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino) +#if defined(__KERNEL__) || defined(_KERNEL) +#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_addr_per_block_bits) +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) +#define EXT2_INODES_PER_BLOCK(s) ((s)->s_inodes_per_block) #else #define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ EXT2_GOOD_OLD_INODE_SIZE : \ @@ -147,12 +158,6 @@ EXT2_GOOD_OLD_FIRST_INO : \ (s)->s_first_ino) #endif -#else /* !notyet */ -#define EXT2_INODES_PER_BLOCK(s) ((s)->s_inodes_per_block) -/* Should be sizeof(struct ext2_inode): */ -#define EXT2_INODE_SIZE(s) ((s)->s_inode_size) -#define EXT2_FIRST_INO(s) ((s)->s_first_inode) -#endif /* notyet */ /* * Macro-instructions used to manage fragments @@ -160,15 +165,11 @@ #define EXT2_MIN_FRAG_SIZE 1024 #define EXT2_MAX_FRAG_SIZE 4096 #define EXT2_MIN_FRAG_LOG_SIZE 10 -#ifdef __KERNEL__ -# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size) -# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block) +#if defined(__KERNEL__) || defined(_KERNEL) +# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) #else -# if defined(_KERNEL) && defined(__FreeBSD__) -# define EXT2_FRAG_SIZE(s) ((s)->s_frag_size) -# else # define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) -# endif # define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) #endif @@ -212,11 +213,11 @@ struct ext2_group_desc /* * Macro-instructions used to manage group descriptors */ -#ifdef __KERNEL__ -# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group) -# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block) -# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group) -# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits) +#if defined(__KERNEL__) || defined(_KERNEL) +# define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) +# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) +# define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) +# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) #else # define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group) # define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) @@ -366,7 +367,7 @@ struct ext2_inode { #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt #define set_opt(o, opt) o |= EXT2_MOUNT_##opt -#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \ +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ EXT2_MOUNT_##opt) /* * Maximal mount counts between two filesystem checks @@ -444,15 +445,6 @@ struct ext2_super_block { __u32 s_reserved[204]; /* Padding to the end of the block */ }; -#ifdef __KERNEL__ -#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -#else -/* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test - * macros from user land. */ -#define EXT2_SB(sb) (sb) -#endif - /* * Codes for operating systems */ @@ -478,11 +470,11 @@ struct ext2_super_block { */ #define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_compat & (mask) ) + ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) ) #define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) + ( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) ) #define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_incompat & (mask) ) + ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) ) #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 diff --git a/sys/gnu/fs/ext2fs/ext2_fs_sb.h b/sys/gnu/fs/ext2fs/ext2_fs_sb.h index ae5c268..2e3d78f 100644 --- a/sys/gnu/fs/ext2fs/ext2_fs_sb.h +++ b/sys/gnu/fs/ext2fs/ext2_fs_sb.h @@ -60,11 +60,9 @@ struct ext2_sb_info { unsigned long s_blocks_per_group;/* Number of blocks in a group */ unsigned long s_inodes_per_group;/* Number of inodes in a group */ unsigned long s_itb_per_group; /* Number of inode table blocks per group */ - unsigned long s_db_per_group; /* Number of descriptor blocks per group */ + unsigned long s_gdb_count; /* Number of group descriptor blocks */ unsigned long s_desc_per_block; /* Number of group descriptors per block */ unsigned long s_groups_count; /* Number of groups in the fs */ - unsigned long s_first_inode; /* First inode on fs */ - unsigned int s_inode_size; /* Size for inode with extra data */ struct buffer_head * s_sbh; /* Buffer containing the super block */ struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */ struct buffer_head ** s_group_desc; @@ -74,10 +72,13 @@ struct ext2_sb_info { struct buffer_head * s_inode_bitmap[EXT2_MAX_GROUP_LOADED]; unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED]; struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED]; - int s_rename_lock; unsigned long s_mount_opt; - unsigned short s_resuid; - unsigned short s_resgid; +#ifdef notyet + uid_t s_resuid; + gid_t s_resgid; +#endif + unsigned short s_inode_size; + unsigned int s_first_ino; unsigned short s_mount_state; /* stuff that FFS keeps in its super block or that linux diff --git a/sys/gnu/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c index 7788d58..261d85f 100644 --- a/sys/gnu/fs/ext2fs/ext2_lookup.c +++ b/sys/gnu/fs/ext2fs/ext2_lookup.c @@ -46,6 +46,7 @@ #include <sys/namei.h> #include <sys/bio.h> #include <sys/buf.h> +#include <sys/endian.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/malloc.h> @@ -771,7 +772,7 @@ ext2_direnter(ip, dvp, cnp) dp = VTOI(dvp); newdir.inode = ip->i_number; newdir.name_len = cnp->cn_namelen; - if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, + if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2_FEATURE_INCOMPAT_FILETYPE)) newdir.file_type = DTTOFT(IFTODT(ip->i_mode)); else @@ -949,7 +950,7 @@ ext2_dirrewrite(dp, ip, cnp) &bp)) != 0) return (error); ep->inode = ip->i_number; - if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, + if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2_FEATURE_INCOMPAT_FILETYPE)) ep->file_type = DTTOFT(IFTODT(ip->i_mode)); else diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c index c8d79fb..6171671 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c @@ -78,13 +78,13 @@ #include <gnu/fs/ext2fs/fs.h> #include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs.h> #include <gnu/fs/ext2fs/ext2_fs_sb.h> +#include <gnu/fs/ext2fs/ext2_fs.h> -static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); -static int ext2_mountfs(struct vnode *, struct mount *); -static int ext2_reload(struct mount *mp, struct thread *td); -static int ext2_sbupdate(struct ext2mount *, int); +static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); +static int ext2_mountfs(struct vnode *, struct mount *); +static int ext2_reload(struct mount *mp, struct thread *td); +static int ext2_sbupdate(struct ext2mount *, int); static vfs_unmount_t ext2_unmount; static vfs_root_t ext2_root; @@ -109,9 +109,6 @@ static struct vfsops ext2fs_vfsops = { VFS_SET(ext2fs_vfsops, ext2fs, 0); -#define bsd_malloc malloc -#define bsd_free free - static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly); static int compute_sb_data(struct vnode * devvp, @@ -127,18 +124,17 @@ static const char *ext2_opts[] = { "from", "export", "acls", "noexec", * mount system call */ static int -ext2_mount(mp) - struct mount *mp; +ext2_mount(struct mount *mp) { struct vfsoptlist *opts; struct vnode *devvp; struct thread *td; struct ext2mount *ump = 0; struct ext2_sb_info *fs; + struct nameidata nd, *ndp = &nd; + accmode_t accmode; char *path, *fspec; int error, flags, len; - accmode_t accmode; - struct nameidata nd, *ndp = &nd; td = curthread; opts = mp->mnt_optnew; @@ -196,6 +192,7 @@ ext2_mount(mp) if (fs->s_rd_only && !vfs_flagopt(opts, "ro", NULL, 0)) { if (ext2_check_sb_compat(fs->s_es, devvp->v_rdev, 0)) return (EPERM); + /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. @@ -221,13 +218,12 @@ ext2_mount(mp) if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 || (fs->s_es->s_state & EXT2_ERROR_FS)) { if (mp->mnt_flag & MNT_FORCE) { - printf( -"WARNING: %s was not properly dismounted\n", - fs->fs_fsmnt); + printf("WARNING: %s was not properly " + "dismounted\n", fs->fs_fsmnt); } else { - printf( -"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", - fs->fs_fsmnt); + printf("WARNING: R/W mount of %s " + "denied. Filesystem is not clean" + " - run fsck\n", fs->fs_fsmnt); return (EPERM); } } @@ -243,6 +239,7 @@ ext2_mount(mp) return (error); } } + /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible disk device. @@ -292,6 +289,7 @@ ext2_mount(mp) } ump = VFSTOEXT2(mp); fs = ump->um_e2fs; + /* * Note that this strncpy() is ok because of a check at the start * of ext2_mount(). @@ -303,63 +301,55 @@ ext2_mount(mp) } /* - * checks that the data in the descriptor blocks make sense - * this is taken from ext2/super.c + * Checks that the data in the descriptor blocks make sense + * this is taken from ext2/super.c. */ -static int ext2_check_descriptors (struct ext2_sb_info * sb) +static int +ext2_check_descriptors(struct ext2_sb_info *sb) { - int i; - int desc_block = 0; - unsigned long block = sb->s_es->s_first_data_block; - struct ext2_group_desc * gdp = NULL; + struct ext2_group_desc *gdp = NULL; + unsigned long block = sb->s_es->s_first_data_block; + int desc_block = 0; + int i; - /* ext2_debug ("Checking group descriptors"); */ - - for (i = 0; i < sb->s_groups_count; i++) - { + for (i = 0; i < sb->s_groups_count; i++) { /* examine next descriptor block */ - if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0) - gdp = (struct ext2_group_desc *) - sb->s_group_desc[desc_block++]->b_data; - if (gdp->bg_block_bitmap < block || - gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) - { - printf ("ext2_check_descriptors: " - "Block bitmap for group %d" - " not in group (block %lu)!\n", - i, (unsigned long) gdp->bg_block_bitmap); - return 0; - } - if (gdp->bg_inode_bitmap < block || - gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) - { - printf ("ext2_check_descriptors: " - "Inode bitmap for group %d" - " not in group (block %lu)!\n", - i, (unsigned long) gdp->bg_inode_bitmap); - return 0; - } - if (gdp->bg_inode_table < block || - gdp->bg_inode_table + sb->s_itb_per_group >= - block + EXT2_BLOCKS_PER_GROUP(sb)) - { - printf ("ext2_check_descriptors: " - "Inode table for group %d" - " not in group (block %lu)!\n", - i, (unsigned long) gdp->bg_inode_table); - return 0; - } - block += EXT2_BLOCKS_PER_GROUP(sb); - gdp++; - } - return 1; + if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0) + gdp = (struct ext2_group_desc *) + sb->s_group_desc[desc_block++]->b_data; + if (gdp->bg_block_bitmap < block || + gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) { + printf ("ext2_check_descriptors: " + "Block bitmap for group %d" + " not in group (block %lu)!\n", + i, (unsigned long) gdp->bg_block_bitmap); + return (0); + } + if (gdp->bg_inode_bitmap < block || + gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) { + printf ("ext2_check_descriptors: " + "Inode bitmap for group %d" + " not in group (block %lu)!\n", + i, (unsigned long) gdp->bg_inode_bitmap); + return (0); + } + if (gdp->bg_inode_table < block || + gdp->bg_inode_table + sb->s_itb_per_group >= + block + EXT2_BLOCKS_PER_GROUP(sb)) { + printf ("ext2_check_descriptors: " + "Inode table for group %d" + " not in group (block %lu)!\n", + i, (unsigned long) gdp->bg_inode_table); + return (0); + } + block += EXT2_BLOCKS_PER_GROUP(sb); + gdp++; + } + return (1); } static int -ext2_check_sb_compat(es, dev, ronly) - struct ext2_super_block *es; - struct cdev *dev; - int ronly; +ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly) { if (es->s_magic != EXT2_SUPER_MAGIC) { @@ -369,16 +359,14 @@ ext2_check_sb_compat(es, dev, ronly) } if (es->s_rev_level > EXT2_GOOD_OLD_REV) { if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) { - printf( -"WARNING: mount of %s denied due to unsupported optional features\n", - devtoname(dev)); + printf("WARNING: mount of %s denied due to unsupported " + "optional features\n", devtoname(dev)); return (1); } if (!ronly && (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) { - printf( -"WARNING: R/W mount of %s denied due to unsupported optional features\n", - devtoname(dev)); + printf("WARNING: R/W mount of %s denied due to " + "unsupported optional features\n", devtoname(dev)); return (1); } } @@ -386,111 +374,101 @@ ext2_check_sb_compat(es, dev, ronly) } /* - * this computes the fields of the ext2_sb_info structure from the - * data in the ext2_super_block structure read in + * This computes the fields of the ext2_sb_info structure from the + * data in the ext2_super_block structure read in. */ -static int compute_sb_data(devvp, es, fs) - struct vnode * devvp; - struct ext2_super_block * es; - struct ext2_sb_info * fs; +static int +compute_sb_data(struct vnode *devvp, struct ext2_super_block *es, + struct ext2_sb_info *fs) { - int db_count, error; - int i, j; - int logic_sb_block = 1; /* XXX for now */ - -#if 1 -#define V(v) -#else -#define V(v) printf(#v"= %lu\n", (unsigned long)fs->v); -#endif + int db_count, error; + int i, j; + int logic_sb_block = 1; /* XXX for now */ + + fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size; + fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size; + fs->s_fsbtodb = es->s_log_block_size + 1; + fs->s_qbmask = fs->s_blocksize - 1; + fs->s_blocksize_bits = es->s_log_block_size + 10; + fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size; + if (fs->s_frag_size) + fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size; + fs->s_blocks_per_group = es->s_blocks_per_group; + fs->s_frags_per_group = es->s_frags_per_group; + fs->s_inodes_per_group = es->s_inodes_per_group; + if (es->s_rev_level == EXT2_GOOD_OLD_REV) { + fs->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; + fs->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; + } else { + fs->s_first_ino = es->s_first_ino; + fs->s_inode_size = es->s_inode_size; - fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size; - V(s_blocksize) - fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size; - V(s_bshift) - fs->s_fsbtodb = es->s_log_block_size + 1; - V(s_fsbtodb) - fs->s_qbmask = fs->s_blocksize - 1; - V(s_qbmask) - fs->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(es); - V(s_blocksize_bits) - fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size; - V(s_frag_size) - if (fs->s_frag_size) - fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size; - V(s_frags_per_block) - fs->s_blocks_per_group = es->s_blocks_per_group; - V(s_blocks_per_group) - fs->s_frags_per_group = es->s_frags_per_group; - V(s_frags_per_group) - fs->s_inodes_per_group = es->s_inodes_per_group; - V(s_inodes_per_group) - fs->s_inode_size = es->s_inode_size; - V(s_inode_size) - fs->s_first_inode = es->s_first_ino; - V(s_first_inode); - fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE(fs); - V(s_inodes_per_block) - fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block; - V(s_itb_per_group) - fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc); - V(s_desc_per_block) - /* s_resuid / s_resgid ? */ - fs->s_groups_count = (es->s_blocks_count - - es->s_first_data_block + - EXT2_BLOCKS_PER_GROUP(fs) - 1) / - EXT2_BLOCKS_PER_GROUP(fs); - V(s_groups_count) - db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) / - EXT2_DESC_PER_BLOCK(fs); - fs->s_db_per_group = db_count; - V(s_db_per_group) - - fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *), - M_EXT2MNT, M_WAITOK); + /* + * Simple sanity check for superblock inode size value. + */ + if (fs->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE || + fs->s_inode_size > fs->s_blocksize || + (fs->s_inode_size & (fs->s_inode_size - 1)) != 0) { + printf("EXT2-fs: invalid inode size %d\n", + fs->s_inode_size); + return (EIO); + } + } + fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE(fs); + fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block; + fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc); + /* s_resuid / s_resgid ? */ + fs->s_groups_count = (es->s_blocks_count - es->s_first_data_block + + EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs); + db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) / + EXT2_DESC_PER_BLOCK(fs); + fs->s_gdb_count = db_count; + fs->s_group_desc = malloc(db_count * sizeof (struct buf *), + M_EXT2MNT, M_WAITOK); - /* adjust logic_sb_block */ - if(fs->s_blocksize > SBSIZE) - /* Godmar thinks: if the blocksize is greater than 1024, then - the superblock is logically part of block zero. + /* + * Adjust logic_sb_block. + * Godmar thinks: if the blocksize is greater than 1024, then + * the superblock is logically part of block zero. */ - logic_sb_block = 0; - - for (i = 0; i < db_count; i++) { - error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1), - fs->s_blocksize, NOCRED, &fs->s_group_desc[i]); - if(error) { - for (j = 0; j < i; j++) - brelse(fs->s_group_desc[j]); - bsd_free(fs->s_group_desc, M_EXT2MNT); - printf("EXT2-fs: unable to read group descriptors (%d)\n", error); - return EIO; + if(fs->s_blocksize > SBSIZE) + logic_sb_block = 0; + + for (i = 0; i < db_count; i++) { + error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1), + fs->s_blocksize, NOCRED, &fs->s_group_desc[i]); + if(error) { + for (j = 0; j < i; j++) + brelse(fs->s_group_desc[j]); + free(fs->s_group_desc, M_EXT2MNT); + printf("EXT2-fs: unable to read group descriptors" + " (%d)\n", error); + return (EIO); + } + LCK_BUF(fs->s_group_desc[i]) } - LCK_BUF(fs->s_group_desc[i]) - } - if(!ext2_check_descriptors(fs)) { - for (j = 0; j < db_count; j++) - ULCK_BUF(fs->s_group_desc[j]) - bsd_free(fs->s_group_desc, M_EXT2MNT); - printf("EXT2-fs: (ext2_check_descriptors failure) " - "unable to read group descriptors\n"); - return EIO; - } - - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) { - fs->s_inode_bitmap_number[i] = 0; - fs->s_inode_bitmap[i] = NULL; - fs->s_block_bitmap_number[i] = 0; - fs->s_block_bitmap[i] = NULL; - } - fs->s_loaded_inode_bitmaps = 0; - fs->s_loaded_block_bitmaps = 0; - if (es->s_rev_level == EXT2_GOOD_OLD_REV || (es->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == 0) - fs->fs_maxfilesize = 0x7fffffff; - else - fs->fs_maxfilesize = 0x7fffffffffffffff; - return 0; + if(!ext2_check_descriptors(fs)) { + for (j = 0; j < db_count; j++) + ULCK_BUF(fs->s_group_desc[j]) + free(fs->s_group_desc, M_EXT2MNT); + printf("EXT2-fs: (ext2_check_descriptors failure) " + "unable to read group descriptors\n"); + return (EIO); + } + for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) { + fs->s_inode_bitmap_number[i] = 0; + fs->s_inode_bitmap[i] = NULL; + fs->s_block_bitmap_number[i] = 0; + fs->s_block_bitmap[i] = NULL; + } + fs->s_loaded_inode_bitmaps = 0; + fs->s_loaded_block_bitmaps = 0; + if (es->s_rev_level == EXT2_GOOD_OLD_REV || + (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == 0) + fs->fs_maxfilesize = 0x7fffffff; + else + fs->fs_maxfilesize = 0x7fffffffffffffff; + return (0); } /* @@ -512,7 +490,7 @@ ext2_reload(struct mount *mp, struct thread *td) struct vnode *vp, *mvp, *devvp; struct inode *ip; struct buf *bp; - struct ext2_super_block * es; + struct ext2_super_block *es; struct ext2_sb_info *fs; int error; @@ -543,7 +521,7 @@ ext2_reload(struct mount *mp, struct thread *td) if((error = compute_sb_data(devvp, es, fs)) != 0) { brelse(bp); - return error; + return (error); } #ifdef UNKLAR if (fs->fs_sbsize < SBSIZE) @@ -569,12 +547,12 @@ loop: } if (vinvalbuf(vp, 0, 0, 0)) panic("ext2_reload: dirty2"); + /* * Step 5: re-read inode data for all active vnodes. */ ip = VTOI(vp); - error = - bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), + error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), (int)fs->s_blocksize, NOCRED, &bp); if (error) { VOP_UNLOCK(vp, 0); @@ -594,17 +572,15 @@ loop: } /* - * Common code for mount and mountroot + * Common code for mount and mountroot. */ static int -ext2_mountfs(devvp, mp) - struct vnode *devvp; - struct mount *mp; +ext2_mountfs(struct vnode *devvp, struct mount *mp) { struct ext2mount *ump; struct buf *bp; struct ext2_sb_info *fs; - struct ext2_super_block * es; + struct ext2_super_block *es; struct cdev *dev = devvp->v_rdev; struct g_consumer *cp; struct bufobj *bo; @@ -653,28 +629,31 @@ ext2_mountfs(devvp, mp) if ((es->s_state & EXT2_VALID_FS) == 0 || (es->s_state & EXT2_ERROR_FS)) { if (ronly || (mp->mnt_flag & MNT_FORCE)) { - printf( -"WARNING: Filesystem was not properly dismounted\n"); + printf("WARNING: Filesystem was not properly " + "dismounted\n"); } else { - printf( -"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n"); + printf("WARNING: R/W mount denied. Filesystem " + "is not clean - run fsck\n"); error = EPERM; goto out; } } - ump = bsd_malloc(sizeof *ump, M_EXT2MNT, M_WAITOK); + ump = malloc(sizeof *ump, M_EXT2MNT, M_WAITOK); bzero((caddr_t)ump, sizeof *ump); - /* I don't know whether this is the right strategy. Note that - we dynamically allocate both an ext2_sb_info and an ext2_super_block - while Linux keeps the super block in a locked buffer + + /* + * I don't know whether this is the right strategy. Note that + * we dynamically allocate both an ext2_sb_info and an ext2_super_block + * while Linux keeps the super block in a locked buffer. */ - ump->um_e2fs = bsd_malloc(sizeof(struct ext2_sb_info), + ump->um_e2fs = malloc(sizeof(struct ext2_sb_info), M_EXT2MNT, M_WAITOK); - ump->um_e2fs->s_es = bsd_malloc(sizeof(struct ext2_super_block), + ump->um_e2fs->s_es = malloc(sizeof(struct ext2_super_block), M_EXT2MNT, M_WAITOK); bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block)); if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs))) goto out; + /* * We don't free the group descriptors allocated by compute_sb_data() * until ext2_unmount(). This is OK since the mount will succeed. @@ -683,8 +662,10 @@ ext2_mountfs(devvp, mp) bp = NULL; fs = ump->um_e2fs; fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */ - /* if the fs is not mounted read-only, make sure the super block is - always written back on a sync() + + /* + * If the fs is not mounted read-only, make sure the super block is + * always written back on a sync(). */ fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0; if (ronly == 0) { @@ -703,9 +684,11 @@ ext2_mountfs(devvp, mp) ump->um_devvp = devvp; ump->um_bo = &devvp->v_bufobj; ump->um_cp = cp; - /* setting those two parameters allowed us to use - ufs_bmap w/o changse ! - */ + + /* + * Setting those two parameters allowed us to use + * ufs_bmap w/o changse! + */ ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs); ump->um_bptrtodb = fs->s_es->s_log_block_size + 1; ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs); @@ -723,21 +706,19 @@ out: PICKUP_GIANT(); } if (ump) { - bsd_free(ump->um_e2fs->s_es, M_EXT2MNT); - bsd_free(ump->um_e2fs, M_EXT2MNT); - bsd_free(ump, M_EXT2MNT); + free(ump->um_e2fs->s_es, M_EXT2MNT); + free(ump->um_e2fs, M_EXT2MNT); + free(ump, M_EXT2MNT); mp->mnt_data = NULL; } return (error); } /* - * unmount system call + * Unmount system call. */ static int -ext2_unmount(mp, mntflags) - struct mount *mp; - int mntflags; +ext2_unmount(struct mount *mp, int mntflags) { struct ext2mount *ump; struct ext2_sb_info *fs; @@ -761,18 +742,17 @@ ext2_unmount(mp, mntflags) } /* release buffers containing group descriptors */ - for(i = 0; i < fs->s_db_per_group; i++) + for(i = 0; i < fs->s_gdb_count; i++) ULCK_BUF(fs->s_group_desc[i]) - bsd_free(fs->s_group_desc, M_EXT2MNT); + free(fs->s_group_desc, M_EXT2MNT); /* release cached inode/block bitmaps */ - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) - if (fs->s_inode_bitmap[i]) - ULCK_BUF(fs->s_inode_bitmap[i]) - - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) - if (fs->s_block_bitmap[i]) - ULCK_BUF(fs->s_block_bitmap[i]) + for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) + if (fs->s_inode_bitmap[i]) + ULCK_BUF(fs->s_inode_bitmap[i]) + for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) + if (fs->s_block_bitmap[i]) + ULCK_BUF(fs->s_block_bitmap[i]) DROP_GIANT(); g_topology_lock(); @@ -780,9 +760,9 @@ ext2_unmount(mp, mntflags) g_topology_unlock(); PICKUP_GIANT(); vrele(ump->um_devvp); - bsd_free(fs->s_es, M_EXT2MNT); - bsd_free(fs, M_EXT2MNT); - bsd_free(ump, M_EXT2MNT); + free(fs->s_es, M_EXT2MNT); + free(fs, M_EXT2MNT); + free(ump, M_EXT2MNT); mp->mnt_data = NULL; MNT_ILOCK(mp); mp->mnt_flag &= ~MNT_LOCAL; @@ -794,10 +774,7 @@ ext2_unmount(mp, mntflags) * Flush out all the files in a filesystem. */ static int -ext2_flushfiles(mp, flags, td) - struct mount *mp; - int flags; - struct thread *td; +ext2_flushfiles(struct mount *mp, int flags, struct thread *td) { int error; @@ -807,17 +784,15 @@ ext2_flushfiles(mp, flags, td) /* * Get file system statistics. - * taken from ext2/super.c ext2_statfs + * taken from ext2/super.c ext2_statfs. */ static int -ext2_statfs(mp, sbp) - struct mount *mp; - struct statfs *sbp; +ext2_statfs(struct mount *mp, struct statfs *sbp) { - unsigned long overhead; struct ext2mount *ump; struct ext2_sb_info *fs; struct ext2_super_block *es; + unsigned long overhead; int i, nsb; ump = VFSTOEXT2(mp); @@ -838,10 +813,10 @@ ext2_statfs(mp, sbp) } else nsb = fs->s_groups_count; overhead = es->s_first_data_block + - /* Superblocks and block group descriptors: */ - nsb * (1 + fs->s_db_per_group) + - /* Inode bitmap, block bitmap, and inode table: */ - fs->s_groups_count * (1 + 1 + fs->s_itb_per_group); + /* Superblocks and block group descriptors: */ + nsb * (1 + fs->s_gdb_count) + + /* Inode bitmap, block bitmap, and inode table: */ + fs->s_groups_count * (1 + 1 + fs->s_itb_per_group); sbp->f_bsize = EXT2_FRAG_SIZE(fs); sbp->f_iosize = EXT2_BLOCK_SIZE(fs); @@ -861,9 +836,7 @@ ext2_statfs(mp, sbp) * Note: we are always called with the filesystem marked `MPBUSY'. */ static int -ext2_sync(mp, waitfor) - struct mount *mp; - int waitfor; +ext2_sync(struct mount *mp, int waitfor) { struct vnode *mvp, *vp; struct thread *td; @@ -878,6 +851,7 @@ ext2_sync(mp, waitfor) printf("fs = %s\n", fs->fs_fsmnt); panic("ext2_sync: rofs mod"); } + /* * Write back each (modified) inode. */ @@ -915,6 +889,7 @@ loop: MNT_ILOCK(mp); } MNT_IUNLOCK(mp); + /* * Force stale file system control information to be flushed. */ @@ -924,6 +899,7 @@ loop: allerror = error; VOP_UNLOCK(ump->um_devvp, 0); } + /* * Write back modified superblock. */ @@ -943,11 +919,7 @@ loop: * done by the calling routine. */ static int -ext2_vget(mp, ino, flags, vpp) - struct mount *mp; - ino_t ino; - int flags; - struct vnode **vpp; +ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) { struct ext2_sb_info *fs; struct inode *ip; @@ -955,9 +927,9 @@ ext2_vget(mp, ino, flags, vpp) struct buf *bp; struct vnode *vp; struct cdev *dev; + struct thread *td; int i, error; int used_blocks; - struct thread *td; td = curthread; error = vfs_hash_get(mp, ino, flags, td, vpp, NULL, NULL); @@ -999,9 +971,6 @@ ext2_vget(mp, ino, flags, vpp) return (error); /* Read in the disk contents for the inode, copy into the inode. */ -#if 0 -printf("ext2_vget(%d) dbn= %lu ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); -#endif if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), (int)fs->s_blocksize, NOCRED, &bp)) != 0) { /* @@ -1023,10 +992,12 @@ printf("ext2_vget(%d) dbn= %lu ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); ip->i_next_alloc_goal = 0; ip->i_prealloc_count = 0; ip->i_prealloc_block = 0; - /* now we want to make sure that block pointers for unused - blocks are zeroed out - ext2_balloc depends on this - although for regular files and directories only - */ + + /* + * Now we want to make sure that block pointers for unused + * blocks are zeroed out - ext2_balloc depends on this + * although for regular files and directories only + */ if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) { used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize; for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) @@ -1046,10 +1017,12 @@ printf("ext2_vget(%d) dbn= %lu ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); *vpp = NULL; return (error); } + /* * Finish inode initialization now that aliasing has been resolved. */ ip->i_devvp = ump->um_devvp; + /* * Set up a generation number for this inode if it does not * already have one. This should only happen on old filesystems. @@ -1074,10 +1047,7 @@ printf("ext2_vget(%d) dbn= %lu ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); * those rights via. exflagsp and credanonp */ static int -ext2_fhtovp(mp, fhp, vpp) - struct mount *mp; - struct fid *fhp; - struct vnode **vpp; +ext2_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct inode *ip; struct ufid *ufhp; @@ -1112,17 +1082,13 @@ ext2_fhtovp(mp, fhp, vpp) * Write a superblock and associated information back to disk. */ static int -ext2_sbupdate(mp, waitfor) - struct ext2mount *mp; - int waitfor; +ext2_sbupdate(struct ext2mount *mp, int waitfor) { struct ext2_sb_info *fs = mp->um_e2fs; struct ext2_super_block *es = fs->s_es; struct buf *bp; int error = 0; -/* -printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no"); -*/ + bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0); bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block)); if (waitfor == MNT_WAIT) @@ -1133,9 +1099,8 @@ printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no"); /* * The buffers for group descriptors, inode bitmaps and block bitmaps * are not busy at this point and are (hopefully) written by the - * usual sync mechanism. No need to write them here - */ - + * usual sync mechanism. No need to write them here. + */ return (error); } @@ -1143,10 +1108,7 @@ printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no"); * Return the root of a filesystem. */ static int -ext2_root(mp, flags, vpp) - struct mount *mp; - int flags; - struct vnode **vpp; +ext2_root(struct mount *mp, int flags, struct vnode **vpp) { struct vnode *nvp; int error; diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c index 1b5023c..248c433 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/gnu/fs/ext2fs/ext2_vnops.c @@ -52,6 +52,7 @@ #include <sys/stat.h> #include <sys/bio.h> #include <sys/buf.h> +#include <sys/endian.h> #include <sys/priv.h> #include <sys/proc.h> #include <sys/mount.h> @@ -1185,7 +1186,7 @@ ext2_mkdir(ap) goto bad; /* Initialize directory with "." and ".." from static template. */ - if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, + if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2_FEATURE_INCOMPAT_FILETYPE)) dtp = &mastertemplate; else diff --git a/sys/gnu/fs/ext2fs/sparc64-bitops.h b/sys/gnu/fs/ext2fs/sparc64-bitops.h deleted file mode 100644 index 26cb578..0000000 --- a/sys/gnu/fs/ext2fs/sparc64-bitops.h +++ /dev/null @@ -1,264 +0,0 @@ -/*- - * $Id: bitops.h,v 1.31 2000/09/23 02:09:21 davem Exp $ - * bitops.h: Bit string operations on the V9. - * - * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* $FreeBSD$ */ -#ifndef _SPARC64_BITOPS_H -#define _SPARC64_BITOPS_H - -#include <asm/byteorder.h> - -extern long __test_and_set_bit(unsigned long nr, volatile void *addr); -extern long __test_and_clear_bit(unsigned long nr, volatile void *addr); -extern long __test_and_change_bit(unsigned long nr, volatile void *addr); - -#define test_and_set_bit(nr,addr) (__test_and_set_bit(nr,addr)!=0) -#define test_and_clear_bit(nr,addr) (__test_and_clear_bit(nr,addr)!=0) -#define test_and_change_bit(nr,addr) (__test_and_change_bit(nr,addr)!=0) -#define set_bit(nr,addr) ((void)__test_and_set_bit(nr,addr)) -#define clear_bit(nr,addr) ((void)__test_and_clear_bit(nr,addr)) -#define change_bit(nr,addr) ((void)__test_and_change_bit(nr,addr)) - -#define smp_mb__before_clear_bit() do { } while(0) -#define smp_mb__after_clear_bit() do { } while(0) - -extern __inline__ int test_bit(int nr, __const__ void *addr) -{ - return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL; -} - -/* The easy/cheese version for now. */ -extern __inline__ unsigned long ffz(unsigned long word) -{ - unsigned long result; - -#ifdef ULTRA_HAS_POPULATION_COUNT /* Thanks for nothing Sun... */ - __asm__ __volatile__(" - brz,pn %0, 1f - neg %0, %%g1 - xnor %0, %%g1, %%g2 - popc %%g2, %0 -1: " : "=&r" (result) - : "0" (word) - : "g1", "g2"); -#else -#if 1 /* def EASY_CHEESE_VERSION */ - result = 0; - while(word & 1) { - result++; - word >>= 1; - } -#else - unsigned long tmp; - - result = 0; - tmp = ~word & -~word; - if (!(unsigned)tmp) { - tmp >>= 32; - result = 32; - } - if (!(unsigned short)tmp) { - tmp >>= 16; - result += 16; - } - if (!(unsigned char)tmp) { - tmp >>= 8; - result += 8; - } - if (tmp & 0xf0) result += 4; - if (tmp & 0xcc) result += 2; - if (tmp & 0xaa) result ++; -#endif -#endif - return result; -} - -#ifdef __KERNEL__ - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ - -#define ffs(x) generic_ffs(x) - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ - -#ifdef ULTRA_HAS_POPULATION_COUNT - -extern __inline__ unsigned int hweight32(unsigned int w) -{ - unsigned int res; - - __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff)); - return res; -} - -extern __inline__ unsigned int hweight16(unsigned int w) -{ - unsigned int res; - - __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff)); - return res; -} - -extern __inline__ unsigned int hweight8(unsigned int w) -{ - unsigned int res; - - __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff)); - return res; -} - -#else - -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -#endif -#endif /* __KERNEL__ */ - -/* find_next_zero_bit() finds the first zero bit in a bit string of length - * 'size' bits, starting the search at bit 'offset'. This is largely based - * on Linus's ALPHA routines, which are pretty portable BTW. - */ - -extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = ((unsigned long *) addr) + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (64-offset); - if (size < 64) - goto found_first; - if (~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -#define find_first_zero_bit(addr, size) \ - find_next_zero_bit((addr), (size), 0) - -extern long __test_and_set_le_bit(int nr, volatile void *addr); -extern long __test_and_clear_le_bit(int nr, volatile void *addr); - -#define test_and_set_le_bit(nr,addr) (__test_and_set_le_bit(nr,addr)!=0) -#define test_and_clear_le_bit(nr,addr) (__test_and_clear_le_bit(nr,addr)!=0) -#define set_le_bit(nr,addr) ((void)__test_and_set_le_bit(nr,addr)) -#define clear_le_bit(nr,addr) ((void)__test_and_clear_le_bit(nr,addr)) - -extern __inline__ int test_le_bit(int nr, __const__ void * addr) -{ - int mask; - __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - return ((mask & *ADDR) != 0); -} - -#define find_first_zero_le_bit(addr, size) \ - find_next_zero_le_bit((addr), (size), 0) - -extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = ((unsigned long *) addr) + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if(offset) { - tmp = __swab64p(p++); - tmp |= (~0UL >> (64-offset)); - if(size < 64) - goto found_first; - if(~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while(size & ~63) { - if(~(tmp = __swab64p(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if(!size) - return result; - tmp = __swab64p(p); -found_first: - tmp |= (~0UL << size); - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -#ifdef __KERNEL__ - -#define ext2_set_bit test_and_set_le_bit -#define ext2_clear_bit test_and_clear_le_bit -#define ext2_test_bit test_le_bit -#define ext2_find_first_zero_bit find_first_zero_le_bit -#define ext2_find_next_zero_bit find_next_zero_le_bit - -/* Bitmap functions for the minix filesystem. */ -#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) -#define minix_set_bit(nr,addr) set_bit(nr,addr) -#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) - -#endif /* __KERNEL__ */ - -#endif /* defined(_SPARC64_BITOPS_H) */ diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 7475efd..08edaf7 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -71,6 +71,7 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev options STOP_NMI # Stop CPUS using NMI instead of IPI options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing +options MAC # TrustedBSD MAC Framework #options KDTRACE_HOOKS # Kernel DTrace hooks # Debugging for use in -current diff --git a/sys/i386/conf/MAC b/sys/i386/conf/MAC deleted file mode 100644 index d208741..0000000 --- a/sys/i386/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/i386 MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC index ab471f7..83d1f60 100644 --- a/sys/ia64/conf/GENERIC +++ b/sys/ia64/conf/GENERIC @@ -40,6 +40,7 @@ options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # required by INVARIANTS options KDB # Enable kernel debugger support options KTRACE # ktrace(1) syscall trace support +options MAC # TrustedBSD MAC Framework options MD_ROOT # MD usable as root device options MSDOSFS # MSDOS Filesystem options NFSCLIENT # Network Filesystem Client diff --git a/sys/ia64/conf/MAC b/sys/ia64/conf/MAC deleted file mode 100644 index a4acaeb..0000000 --- a/sys/ia64/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/ia64 MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index c93d05a..1221825 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2075,9 +2075,13 @@ fget_unlocked(struct filedesc *fdp, int fd) count = fp->f_count; if (count == 0) continue; - if (atomic_cmpset_int(&fp->f_count, count, count + 1) != 1) + /* + * Use an acquire barrier to prevent caching of fd_ofiles + * so it is refreshed for verification. + */ + if (atomic_cmpset_acq_int(&fp->f_count, count, count + 1) != 1) continue; - if (fp == ((struct file *volatile*)fdp->fd_ofiles)[fd]) + if (fp == fdp->fd_ofiles[fd]) break; fdrop(fp, curthread); } diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index f03ddbc..c365e65 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -51,8 +51,7 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> #endif -CTASSERT(((LK_CANRECURSE | LK_NOSHARE) & LO_CLASSFLAGS) == - (LK_CANRECURSE | LK_NOSHARE)); +CTASSERT((LK_NOSHARE & LO_CLASSFLAGS) == LK_NOSHARE); #define SQ_EXCLUSIVE_QUEUE 0 #define SQ_SHARED_QUEUE 1 @@ -316,7 +315,9 @@ lockinit(struct lock *lk, int pri, const char *wmesg, int timo, int flags) MPASS((flags & ~LK_INIT_MASK) == 0); - iflags = LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE; + iflags = LO_SLEEPABLE | LO_UPGRADABLE; + if (flags & LK_CANRECURSE) + iflags |= LO_RECURSABLE; if ((flags & LK_NODUP) == 0) iflags |= LO_DUPOK; if (flags & LK_NOPROFILE) @@ -325,7 +326,7 @@ lockinit(struct lock *lk, int pri, const char *wmesg, int timo, int flags) iflags |= LO_WITNESS; if (flags & LK_QUIET) iflags |= LO_QUIET; - iflags |= flags & (LK_CANRECURSE | LK_NOSHARE); + iflags |= flags & LK_NOSHARE; lk->lk_lock = LK_UNLOCKED; lk->lk_recurse = 0; @@ -530,7 +531,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, */ if (lockmgr_xlocked(lk)) { if ((flags & LK_CANRECURSE) == 0 && - (lk->lock_object.lo_flags & LK_CANRECURSE) == 0) { + (lk->lock_object.lo_flags & LO_RECURSABLE) == 0) { /* * If the lock is expected to not panic just diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index a1a55f2..4e0bdf0 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1690,9 +1690,7 @@ cr_canseesocket(struct ucred *cred, struct socket *so) if (error) return (ENOENT); #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_visible(cred, so); - SOCK_UNLOCK(so); if (error) return (error); #endif diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 28fccce..c07f595 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -51,8 +51,6 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> -CTASSERT((RW_RECURSE & LO_CLASSFLAGS) == RW_RECURSE); - #if defined(SMP) && !defined(NO_ADAPTIVE_RWLOCKS) #define ADAPTIVE_RWLOCKS #endif @@ -177,16 +175,17 @@ rw_init_flags(struct rwlock *rw, const char *name, int opts) MPASS((opts & ~(RW_DUPOK | RW_NOPROFILE | RW_NOWITNESS | RW_QUIET | RW_RECURSE)) == 0); - flags = LO_UPGRADABLE | LO_RECURSABLE; + flags = LO_UPGRADABLE; if (opts & RW_DUPOK) flags |= LO_DUPOK; if (opts & RW_NOPROFILE) flags |= LO_NOPROFILE; if (!(opts & RW_NOWITNESS)) flags |= LO_WITNESS; + if (opts & RW_RECURSE) + flags |= LO_RECURSABLE; if (opts & RW_QUIET) flags |= LO_QUIET; - flags |= opts & RW_RECURSE; rw->rw_lock = RW_UNLOCKED; rw->rw_recurse = 0; @@ -249,7 +248,8 @@ _rw_try_wlock(struct rwlock *rw, const char *file, int line) KASSERT(rw->rw_lock != RW_DESTROYED, ("rw_try_wlock() of destroyed rwlock @ %s:%d", file, line)); - if (rw_wlocked(rw) && (rw->lock_object.lo_flags & RW_RECURSE) != 0) { + if (rw_wlocked(rw) && + (rw->lock_object.lo_flags & LO_RECURSABLE) != 0) { rw->rw_recurse++; rval = 1; } else @@ -646,7 +646,7 @@ _rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line) #endif if (rw_wlocked(rw)) { - KASSERT(rw->lock_object.lo_flags & RW_RECURSE, + KASSERT(rw->lock_object.lo_flags & LO_RECURSABLE, ("%s: recursing but non-recursive rw %s @ %s:%d\n", __func__, rw->lock_object.lo_name, file, line)); rw->rw_recurse++; diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c index 6342252..04c2c98 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -66,8 +66,7 @@ __FBSDID("$FreeBSD$"); #define ADAPTIVE_SX #endif -CTASSERT(((SX_NOADAPTIVE | SX_RECURSE) & LO_CLASSFLAGS) == - (SX_NOADAPTIVE | SX_RECURSE)); +CTASSERT((SX_NOADAPTIVE & LO_CLASSFLAGS) == SX_NOADAPTIVE); /* Handy macros for sleep queues. */ #define SQ_EXCLUSIVE_QUEUE 0 @@ -207,17 +206,19 @@ sx_init_flags(struct sx *sx, const char *description, int opts) MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK | SX_NOPROFILE | SX_NOADAPTIVE)) == 0); - flags = LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE; + flags = LO_SLEEPABLE | LO_UPGRADABLE; if (opts & SX_DUPOK) flags |= LO_DUPOK; if (opts & SX_NOPROFILE) flags |= LO_NOPROFILE; if (!(opts & SX_NOWITNESS)) flags |= LO_WITNESS; + if (opts & SX_RECURSE) + flags |= LO_RECURSABLE; if (opts & SX_QUIET) flags |= LO_QUIET; - flags |= opts & (SX_NOADAPTIVE | SX_RECURSE); + flags |= opts & SX_NOADAPTIVE; sx->sx_lock = SX_LOCK_UNLOCKED; sx->sx_recurse = 0; lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags); @@ -305,7 +306,8 @@ _sx_try_xlock(struct sx *sx, const char *file, int line) KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, ("sx_try_xlock() of destroyed sx @ %s:%d", file, line)); - if (sx_xlocked(sx) && (sx->lock_object.lo_flags & SX_RECURSE) != 0) { + if (sx_xlocked(sx) && + (sx->lock_object.lo_flags & LO_RECURSABLE) != 0) { sx->sx_recurse++; atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED); rval = 1; @@ -479,7 +481,7 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file, /* If we already hold an exclusive lock, then recurse. */ if (sx_xlocked(sx)) { - KASSERT((sx->lock_object.lo_flags & SX_RECURSE) != 0, + KASSERT((sx->lock_object.lo_flags & LO_RECURSABLE) != 0, ("_sx_xlock_hard: recursed on non-recursive sx %s @ %s:%d\n", sx->lock_object.lo_name, file, line)); sx->sx_recurse++; diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 61b0361..5e5695c 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -78,9 +78,7 @@ soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred, int error; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_receive(active_cred, so); - SOCK_UNLOCK(so); if (error) return (error); #endif @@ -99,9 +97,7 @@ soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred, int error; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_send(active_cred, so); - SOCK_UNLOCK(so); if (error) return (error); #endif @@ -222,9 +218,7 @@ soo_poll(struct file *fp, int events, struct ucred *active_cred, #ifdef MAC int error; - SOCK_LOCK(so); error = mac_socket_check_poll(active_cred, so); - SOCK_UNLOCK(so); if (error) return (error); #endif @@ -243,9 +237,7 @@ soo_stat(struct file *fp, struct stat *ub, struct ucred *active_cred, bzero((caddr_t)ub, sizeof (*ub)); ub->st_mode = S_IFSOCK; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_stat(active_cred, so); - SOCK_UNLOCK(so); if (error) return (error); #endif diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index bf24132..ea53885 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$"); #include <sys/protosw.h> #include <sys/uio.h> -#include <security/mac/mac_framework.h> - int max_linkhdr; int max_protohdr; int max_hdr; diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index a12c731..00fb438 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -274,7 +274,7 @@ shm_dotruncate(struct shmfd *shmfd, off_t length) /* * If the last page is partially mapped, then zero out * the garbage at the end of the page. See comments - * in vnode_page_setsize() for more details. + * in vnode_pager_setsize() for more details. * * XXXJHB: This handles in memory pages, but what about * a page swapped out to disk? @@ -286,10 +286,23 @@ shm_dotruncate(struct shmfd *shmfd, off_t length) int size = PAGE_SIZE - base; pmap_zero_page_area(m, base, size); + + /* + * Update the valid bits to reflect the blocks that + * have been zeroed. Some of these valid bits may + * have already been set. + */ + vm_page_set_valid(m, base, size); + + /* + * Round "base" to the next block boundary so that the + * dirty bit for a partially zeroed block is not + * cleared. + */ + base = roundup2(base, DEV_BSIZE); + vm_page_lock_queues(); - vm_page_set_validclean(m, base, size); - if (m->dirty != 0) - m->dirty = VM_PAGE_BITS_ALL; + vm_page_clear_dirty(m, base, PAGE_SIZE - base); vm_page_unlock_queues(); } else if ((length & PAGE_MASK) && __predict_false(object->cache != NULL)) { diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 80f9a55..7341d3f 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -444,9 +444,7 @@ sonewconn(struct socket *head, int connstatus) so->so_proto = head->so_proto; so->so_cred = crhold(head->so_cred); #ifdef MAC - SOCK_LOCK(head); mac_socket_newconn(head, so); - SOCK_UNLOCK(head); #endif knlist_init(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv), NULL, NULL, NULL); diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 66eb7e1..964547c 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -221,16 +221,10 @@ kern_bind(td, fd, sa) ktrsockaddr(sa); #endif #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_bind(td->td_ucred, so, sa); - SOCK_UNLOCK(so); - if (error) - goto done; -#endif - error = sobind(so, sa, td); -#ifdef MAC -done: + if (error == 0) #endif + error = sobind(so, sa, td); fdrop(fp, td); return (error); } @@ -252,17 +246,14 @@ listen(td, uap) if (error == 0) { so = fp->f_data; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_listen(td->td_ucred, so); - SOCK_UNLOCK(so); - if (error) - goto done; + if (error == 0) { #endif - CURVNET_SET(so->so_vnet); - error = solisten(so, uap->backlog, td); - CURVNET_RESTORE(); + CURVNET_SET(so->so_vnet); + error = solisten(so, uap->backlog, td); + CURVNET_RESTORE(); #ifdef MAC -done: + } #endif fdrop(fp, td); } @@ -354,9 +345,7 @@ kern_accept(struct thread *td, int s, struct sockaddr **name, goto done; } #ifdef MAC - SOCK_LOCK(head); error = mac_socket_check_accept(td->td_ucred, head); - SOCK_UNLOCK(head); if (error != 0) goto done; #endif @@ -549,9 +538,7 @@ kern_connect(td, fd, sa) ktrsockaddr(sa); #endif #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_connect(td->td_ucred, so, sa); - SOCK_UNLOCK(so); if (error) goto bad; #endif @@ -603,7 +590,6 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol, if (error) return (error); #endif - error = socreate(domain, &so1, type, protocol, td->td_ucred, td); if (error) return (error); @@ -752,13 +738,13 @@ kern_sendit(td, s, mp, flags, control, segflg) so = (struct socket *)fp->f_data; #ifdef MAC - SOCK_LOCK(so); - if (mp->msg_name != NULL) + if (mp->msg_name != NULL) { error = mac_socket_check_connect(td->td_ucred, so, mp->msg_name); - if (error == 0) - error = mac_socket_check_send(td->td_ucred, so); - SOCK_UNLOCK(so); + if (error) + goto bad; + } + error = mac_socket_check_send(td->td_ucred, so); if (error) goto bad; #endif @@ -951,9 +937,7 @@ kern_recvit(td, s, mp, fromseg, controlp) so = fp->f_data; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_receive(td->td_ucred, so); - SOCK_UNLOCK(so); if (error) { fdrop(fp, td); return (error); @@ -1887,9 +1871,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap, } #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_send(td->td_ucred, so); - SOCK_UNLOCK(so); if (error) goto out; #endif @@ -2417,9 +2399,7 @@ sctp_generic_sendmsg (td, uap) so = (struct socket *)fp->f_data; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_send(td->td_ucred, so); - SOCK_UNLOCK(so); if (error) goto sctp_bad; #endif /* MAC */ @@ -2521,9 +2501,7 @@ sctp_generic_sendmsg_iov(td, uap) so = (struct socket *)fp->f_data; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_send(td->td_ucred, so); - SOCK_UNLOCK(so); if (error) goto sctp_bad; #endif /* MAC */ @@ -2618,9 +2596,7 @@ sctp_generic_recvmsg(td, uap) so = fp->f_data; #ifdef MAC - SOCK_LOCK(so); error = mac_socket_check_receive(td->td_ucred, so); - SOCK_UNLOCK(so); if (error) { goto out; return (error); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 2f33008..c9e7d39 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1246,10 +1246,8 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) UNP_PCB_UNLOCK(unp2); UNP_PCB_UNLOCK(unp); #ifdef MAC - SOCK_LOCK(so); mac_socketpeer_set_from_socket(so, so3); mac_socketpeer_set_from_socket(so3, so); - SOCK_UNLOCK(so); #endif so2 = so3; diff --git a/sys/net/if.c b/sys/net/if.c index 9a3c1fd..ffff619 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -574,6 +574,7 @@ if_free_internal(struct ifnet *ifp) knlist_destroy(&ifp->if_klist); IF_AFDATA_DESTROY(ifp); IF_ADDR_LOCK_DESTROY(ifp); + ifq_detach(&ifp->if_snd); free(ifp, M_IFNET); } @@ -1025,9 +1026,6 @@ if_detach_internal(struct ifnet *ifp, int vmove) } ifp->if_afdata_initialized = 0; IF_AFDATA_UNLOCK(ifp); - - if (!vmove) - ifq_detach(&ifp->if_snd); } #ifdef VIMAGE diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 22c690c..092514b 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -313,6 +313,8 @@ ieee80211_ifdetach(struct ieee80211com *ic) struct ifnet *ifp = ic->ic_ifp; struct ieee80211vap *vap; + if_detach(ifp); + while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) ieee80211_vap_destroy(vap); ieee80211_waitfor_parent(ic); @@ -329,11 +331,10 @@ ieee80211_ifdetach(struct ieee80211com *ic) ieee80211_crypto_detach(ic); ieee80211_power_detach(ic); ieee80211_node_detach(ic); - ifmedia_removeall(&ic->ic_media); + ifmedia_removeall(&ic->ic_media); taskqueue_free(ic->ic_tq); IEEE80211_LOCK_DESTROY(ic); - if_detach(ifp); } /* @@ -513,8 +514,6 @@ ieee80211_vap_attach(struct ieee80211vap *vap, IEEE80211_LOCK(ic); TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next); - if (vap->iv_opmode == IEEE80211_M_MONITOR) - ic->ic_monvaps++; ieee80211_syncflag_locked(ic, IEEE80211_F_WME); #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP); @@ -546,24 +545,10 @@ ieee80211_vap_detach(struct ieee80211vap *vap) __func__, ieee80211_opmode_name[vap->iv_opmode], ic->ic_ifp->if_xname); - IEEE80211_LOCK(ic); - /* block traffic from above */ - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - /* - * Evil hack. Clear the backpointer from the ifnet to the - * vap so any requests from above will return an error or - * be ignored. In particular this short-circuits requests - * by the bridge to turn off promiscuous mode as a result - * of calling ether_ifdetach. - */ - ifp->if_softc = NULL; - /* - * Stop the vap before detaching the ifnet. Ideally we'd - * do this in the other order so the ifnet is inaccessible - * while we cleanup internal state but that is hard. - */ - ieee80211_stop_locked(vap); - IEEE80211_UNLOCK(ic); + /* NB: bpfdetach is called by ether_ifdetach and claims all taps */ + ether_ifdetach(ifp); + + ieee80211_stop(vap); /* * Flush any deferred vap tasks. @@ -575,8 +560,6 @@ ieee80211_vap_detach(struct ieee80211vap *vap) IEEE80211_LOCK(ic); KASSERT(vap->iv_state == IEEE80211_S_INIT , ("vap still running")); TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next); - if (vap->iv_opmode == IEEE80211_M_MONITOR) - ic->ic_monvaps--; ieee80211_syncflag_locked(ic, IEEE80211_F_WME); #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP); @@ -591,10 +574,6 @@ ieee80211_vap_detach(struct ieee80211vap *vap) ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); IEEE80211_UNLOCK(ic); - /* XXX can't hold com lock */ - /* NB: bpfdetach is called by ether_ifdetach and claims all taps */ - ether_ifdetach(ifp); - ifmedia_removeall(&vap->iv_media); ieee80211_radiotap_vdetach(vap); @@ -1207,7 +1186,7 @@ ieee80211_media_change(struct ifnet *ifp) return EINVAL; if (vap->iv_des_mode != newmode) { vap->iv_des_mode = newmode; - return ENETRESET; + /* XXX kick state machine if up+running */ } return 0; } diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index 8545140..2b66d6b 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -584,6 +584,11 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showp db_printf(" lastnonht %d", ic->ic_lastnonht); db_printf("\n"); + db_printf("\tsuperg %p\n", ic->ic_superg); + + db_printf("\tmontaps %d th %p txchan %p rh %p rxchan %p\n", + ic->ic_montaps, ic->ic_th, ic->ic_txchan, ic->ic_rh, ic->ic_rxchan); + if (showprocs) { DB_PRINTSYM("\t", "ic_vap_create", ic->ic_vap_create); DB_PRINTSYM("\t", "ic_vap_delete", ic->ic_vap_delete); diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 0dfa4a9..47a76bb 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -706,11 +706,15 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) * vap. This flag is used by drivers to prepare radiotap * state only when needed. */ - if (attach) + if (attach) { ieee80211_syncflag_ext(vap, IEEE80211_FEXT_BPF); - /* NB: if_softc is NULL on vap detach */ - else if (vap != NULL && !bpf_peers_present(vap->iv_rawbpf)) + if (vap->iv_opmode == IEEE80211_M_MONITOR) + atomic_add_int(&vap->iv_ic->ic_montaps, 1); + } else if (!bpf_peers_present(vap->iv_rawbpf)) { ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_BPF); + if (vap->iv_opmode == IEEE80211_M_MONITOR) + atomic_subtract_int(&vap->iv_ic->ic_montaps, 1); + } } } diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index ee83eace..eec52f9 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -302,6 +302,9 @@ hostap_deliver_data(struct ieee80211vap *vap, struct ether_header *eh = mtod(m, struct ether_header *); struct ifnet *ifp = vap->iv_ifp; + /* clear driver/net80211 flags before passing up */ + m->m_flags &= ~(M_80211_RX | M_MCAST | M_BCAST); + KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP, ("gack, opmode %d", vap->iv_opmode)); /* @@ -316,9 +319,6 @@ hostap_deliver_data(struct ieee80211vap *vap, } else IEEE80211_NODE_STAT(ni, rx_ucast); - /* clear driver/net80211 flags before passing up */ - m->m_flags &= ~M_80211_RX; - /* perform as a bridge within the AP */ if ((vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0) { struct mbuf *mcopy = NULL; diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 6e06918..53c2285 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -60,11 +60,16 @@ ieee80211_input_all(struct ieee80211com *ic, struct mbuf *m, int rssi, int nf) struct ieee80211vap *vap; int type = -1; + m->m_flags |= M_BCAST; /* NB: mark for bpf tap'ing */ + /* XXX locking */ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { struct ieee80211_node *ni; struct mbuf *mcopy; + /* NB: could check for IFF_UP but this is cheaper */ + if (vap->iv_state == IEEE80211_S_INIT) + continue; /* * WDS vap's only receive directed traffic from the * station at the ``far end''. That traffic should @@ -196,6 +201,9 @@ ieee80211_deliver_data(struct ieee80211vap *vap, struct ether_header *eh = mtod(m, struct ether_header *); struct ifnet *ifp = vap->iv_ifp; + /* clear driver/net80211 flags before passing up */ + m->m_flags &= ~(M_80211_RX | M_MCAST | M_BCAST); + /* NB: see hostap_deliver_data, this path doesn't handle hostap */ KASSERT(vap->iv_opmode != IEEE80211_M_HOSTAP, ("gack, hostap")); /* @@ -211,9 +219,6 @@ ieee80211_deliver_data(struct ieee80211vap *vap, IEEE80211_NODE_STAT(ni, rx_ucast); m->m_pkthdr.rcvif = ifp; - /* clear driver/net80211 flags before passing up */ - m->m_flags &= ~M_80211_RX; - if (ni->ni_vlan != 0) { /* attach vlan tag */ m->m_pkthdr.ether_vtag = ni->ni_vlan; diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index d40680a..36c6f4c 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_input.h> #define IS_UP_AUTO(_vap) \ - (IFNET_IS_UP_RUNNING(vap->iv_ifp) && \ + (IFNET_IS_UP_RUNNING((_vap)->iv_ifp) && \ (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO) static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; @@ -3202,29 +3202,14 @@ ieee80211_ioctl_updatemulti(struct ieee80211com *ic) int ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { - struct ieee80211vap *vap; - struct ieee80211com *ic; + struct ieee80211vap *vap = ifp->if_softc; + struct ieee80211com *ic = vap->iv_ic; int error = 0; struct ifreq *ifr; struct ifaddr *ifa; /* XXX */ - vap = ifp->if_softc; - if (vap == NULL) { - /* - * During detach we clear the backpointer in the softc - * so any ioctl request through the ifnet that arrives - * before teardown is ignored/rejected. In particular - * this hack handles destroying a vap used by an app - * like wpa_supplicant that will respond to the vap - * being forced into INIT state by immediately trying - * to force it back up. We can yank this hack if/when - * we can destroy the ifnet before cleaning up vap state. - */ - return ENXIO; - } switch (cmd) { case SIOCSIFFLAGS: - ic = vap->iv_ic; IEEE80211_LOCK(ic); ieee80211_syncifflag_locked(ic, IFF_PROMISC); ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); @@ -3250,7 +3235,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCADDMULTI: case SIOCDELMULTI: - ieee80211_ioctl_updatemulti(vap->iv_ic); + ieee80211_ioctl_updatemulti(ic); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: diff --git a/sys/net80211/ieee80211_monitor.c b/sys/net80211/ieee80211_monitor.c index 3f2c847..e324081 100644 --- a/sys/net80211/ieee80211_monitor.c +++ b/sys/net80211/ieee80211_monitor.c @@ -127,6 +127,9 @@ static int monitor_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) { struct ieee80211vap *vap = ni->ni_vap; + struct ifnet *ifp = vap->iv_ifp; + + ifp->if_ipackets++; if (ieee80211_radiotap_active_vap(vap)) ieee80211_radiotap_rx(vap, m); diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 99b995c8..7e69929 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -1220,22 +1220,12 @@ ieee80211_init(void *arg) { struct ieee80211vap *vap = arg; - /* - * This routine is publicly accessible through the vap's - * if_init method so guard against calls during detach. - * ieee80211_vap_detach null's the backpointer before - * tearing down state to signal any callback should be - * rejected/ignored. - */ - if (vap != NULL) { - IEEE80211_DPRINTF(vap, - IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, - "%s\n", __func__); - - IEEE80211_LOCK(vap->iv_ic); - ieee80211_start_locked(vap); - IEEE80211_UNLOCK(vap->iv_ic); - } + IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, + "%s\n", __func__); + + IEEE80211_LOCK(vap->iv_ic); + ieee80211_start_locked(vap); + IEEE80211_UNLOCK(vap->iv_ic); } /* diff --git a/sys/net80211/ieee80211_radiotap.c b/sys/net80211/ieee80211_radiotap.c index 9c8dc4d..b39a071 100644 --- a/sys/net80211/ieee80211_radiotap.c +++ b/sys/net80211/ieee80211_radiotap.c @@ -168,6 +168,7 @@ ieee80211_radiotap_chan_change(struct ieee80211com *ic) } } +#if 0 static void dispatch_radiotap(struct ieee80211vap *vap0, struct mbuf *m, struct ieee80211_radiotap_header *rh) @@ -175,17 +176,46 @@ dispatch_radiotap(struct ieee80211vap *vap0, struct mbuf *m, struct ieee80211com *ic = vap0->iv_ic; int len = le16toh(rh->it_len); - if (ieee80211_radiotap_active_vap(vap0)) + if (vap0->iv_flags_ext & IEEE80211_FEXT_BPF) bpf_mtap2(vap0->iv_rawbpf, rh, len, m); - if (ic->ic_monvaps) { + /* + * Spam monitor mode vaps with unicast frames. Multicast + * frames are handled by passing through ieee80211_input_all + * which distributes copies to the monitor mode vaps to be + * processed above. + */ + if (ic->ic_montaps != 0 && (m->m_flags & M_BCAST) == 0) { struct ieee80211vap *vap; TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - if (vap->iv_opmode == IEEE80211_M_MONITOR && - vap != vap0 && ieee80211_radiotap_active_vap(vap)) + if (vap != vap0 && + vap->iv_opmode == IEEE80211_M_MONITOR && + (vap->iv_flags_ext & IEEE80211_FEXT_BPF) && + vap->iv_state != IEEE80211_S_INIT) bpf_mtap2(vap->iv_rawbpf, rh, len, m); } } } +#endif + +/* + * Distribute radiotap data (+packet) to all monitor mode + * vaps with an active tap other than vap0. + */ +static void +spam_vaps(struct ieee80211vap *vap0, struct mbuf *m, + struct ieee80211_radiotap_header *rh, int len) +{ + struct ieee80211com *ic = vap0->iv_ic; + struct ieee80211vap *vap; + + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + if (vap != vap0 && + vap->iv_opmode == IEEE80211_M_MONITOR && + (vap->iv_flags_ext & IEEE80211_FEXT_BPF) && + vap->iv_state != IEEE80211_S_INIT) + bpf_mtap2(vap->iv_rawbpf, rh, len, m); + } +} /* * Dispatch radiotap data for transmitted packet. @@ -193,8 +223,20 @@ dispatch_radiotap(struct ieee80211vap *vap0, struct mbuf *m, void ieee80211_radiotap_tx(struct ieee80211vap *vap0, struct mbuf *m) { - KASSERT(vap0->iv_ic->ic_th != NULL, ("no tx radiotap header")); - dispatch_radiotap(vap0, m, vap0->iv_ic->ic_th); + struct ieee80211com *ic = vap0->iv_ic; + struct ieee80211_radiotap_header *th = ic->ic_th; + int len; + + KASSERT(th != NULL, ("no tx radiotap header")); + len = le16toh(th->it_len); + + if (vap0->iv_flags_ext & IEEE80211_FEXT_BPF) + bpf_mtap2(vap0->iv_rawbpf, th, len, m); + /* + * Spam monitor mode vaps. + */ + if (ic->ic_montaps != 0) + spam_vaps(vap0, m, th, len); } /* @@ -203,8 +245,22 @@ ieee80211_radiotap_tx(struct ieee80211vap *vap0, struct mbuf *m) void ieee80211_radiotap_rx(struct ieee80211vap *vap0, struct mbuf *m) { - KASSERT(vap0->iv_ic->ic_rh != NULL, ("no rx radiotap header")); - dispatch_radiotap(vap0, m, vap0->iv_ic->ic_rh); + struct ieee80211com *ic = vap0->iv_ic; + struct ieee80211_radiotap_header *rh = ic->ic_rh; + int len; + + KASSERT(rh != NULL, ("no rx radiotap header")); + len = le16toh(rh->it_len); + + if (vap0->iv_flags_ext & IEEE80211_FEXT_BPF) + bpf_mtap2(vap0->iv_rawbpf, rh, len, m); + /* + * Spam monitor mode vaps with unicast frames. Multicast + * frames are handled by passing through ieee80211_input_all + * which distributes copies to the monitor mode vaps. + */ + if (ic->ic_montaps != 0 && (m->m_flags & M_BCAST) == 0) + spam_vaps(vap0, m, rh, len); } /* @@ -221,7 +277,8 @@ ieee80211_radiotap_rx_all(struct ieee80211com *ic, struct mbuf *m) /* XXX locking? */ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - if (ieee80211_radiotap_active_vap(vap)) + if (ieee80211_radiotap_active_vap(vap) && + vap->iv_state != IEEE80211_S_INIT) bpf_mtap2(vap->iv_rawbpf, rh, len, m); } } diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c index b41ed59..951e762 100644 --- a/sys/net80211/ieee80211_scan.c +++ b/sys/net80211/ieee80211_scan.c @@ -131,6 +131,7 @@ ieee80211_scan_detach(struct ieee80211com *ic) scan_signal(ss); IEEE80211_UNLOCK(ic); ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); + callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer); KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scan still running")); if (ss->ss_ops != NULL) { diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 31037fe..3e999c8 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -215,7 +215,7 @@ struct ieee80211com { void *ic_txchan; /* channel state in ic_th */ struct ieee80211_radiotap_header *ic_rh;/* rx radiotap headers */ void *ic_rxchan; /* channel state in ic_rh */ - int ic_monvaps; /* # monitor mode vaps */ + int ic_montaps; /* active monitor mode taps */ /* virtual ap create/delete */ struct ieee80211vap* (*ic_vap_create)(struct ieee80211com *, @@ -669,7 +669,8 @@ ieee80211_radiotap_active(const struct ieee80211com *ic) static __inline int ieee80211_radiotap_active_vap(const struct ieee80211vap *vap) { - return (vap->iv_flags_ext & IEEE80211_FEXT_BPF) != 0; + return (vap->iv_flags_ext & IEEE80211_FEXT_BPF) || + vap->iv_ic->ic_montaps != 0; } /* diff --git a/sys/netatalk/ddp_input.c b/sys/netatalk/ddp_input.c index 2e7dac8..d90b2e8 100644 --- a/sys/netatalk/ddp_input.c +++ b/sys/netatalk/ddp_input.c @@ -410,12 +410,8 @@ ddp_input(struct mbuf *m, struct ifnet *ifp, struct elaphdr *elh, int phase) goto out; #ifdef MAC - SOCK_LOCK(ddp->ddp_socket); - if (mac_socket_check_deliver(ddp->ddp_socket, m) != 0) { - SOCK_UNLOCK(ddp->ddp_socket); + if (mac_socket_check_deliver(ddp->ddp_socket, m) != 0) goto out; - } - SOCK_UNLOCK(ddp->ddp_socket); #endif /* diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 0b4ef27..140f41a 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -212,9 +212,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) error = mac_inpcb_init(inp, M_NOWAIT); if (error != 0) goto out; - SOCK_LOCK(so); mac_inpcb_create(so, inp); - SOCK_UNLOCK(so); #endif #ifdef IPSEC error = ipsec_init_policy(so, &inp->inp_sp); diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 5e71d4d..0894bfa4 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -467,9 +467,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, m->m_pkthdr.rcvif = ifa->ifa_ifp; } #ifdef MAC - SOCK_LOCK(so); mac_socket_create_mbuf(so, m); - SOCK_UNLOCK(so); #endif /* Send packet to input processing via netisr */ netisr_queue_src(NETISR_IP, (uintptr_t)so, m); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index bbf5d8f..674c77e 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1562,9 +1562,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, TCPSTAT_INC(tcps_connects); soisconnected(so); #ifdef MAC - SOCK_LOCK(so); mac_socketpeer_set_from_mbuf(m, so); - SOCK_UNLOCK(so); #endif /* Do window scaling on this connection? */ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 8e80842..2763183 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -635,9 +635,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) goto abort2; } #ifdef MAC - SOCK_LOCK(so); mac_socketpeer_set_from_mbuf(m, so); - SOCK_UNLOCK(so); #endif inp = sotoinpcb(so); diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index 539feab..82b8888 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -73,6 +73,7 @@ options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing +options MAC # TrustedBSD MAC Framework # Debugging for use in -current options KDB # Enable kernel debugger support. diff --git a/sys/pc98/conf/MAC b/sys/pc98/conf/MAC deleted file mode 100644 index 6aee5da..0000000 --- a/sys/pc98/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/pc98 MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC index 819d768..2f9b264 100644 --- a/sys/powerpc/conf/GENERIC +++ b/sys/powerpc/conf/GENERIC @@ -64,6 +64,7 @@ options SYSVSEM #SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing +options MAC # TrustedBSD MAC Framework # Debugging for use in -current options KDB #Enable the kernel debugger diff --git a/sys/powerpc/conf/MAC b/sys/powerpc/conf/MAC deleted file mode 100644 index 8626383..0000000 --- a/sys/powerpc/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/powerpc MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index 9f6a4a4..be366de 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -271,9 +271,7 @@ svc_vc_accept(struct socket *head, struct socket **sop) goto done; } #ifdef MAC - SOCK_LOCK(head); error = mac_socket_check_accept(td->td_ucred, head); - SOCK_UNLOCK(head); if (error != 0) goto done; #endif diff --git a/sys/security/mac/mac_atalk.c b/sys/security/mac/mac_atalk.c index 7ca338e..18bbb8d 100644 --- a/sys/security/mac/mac_atalk.c +++ b/sys/security/mac/mac_atalk.c @@ -61,6 +61,9 @@ mac_netatalk_aarp_send(struct ifnet *ifp, struct mbuf *m) { struct label *mlabel; + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); MAC_IFNET_LOCK(ifp); diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index 6f675cb..1f43c02 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -179,6 +179,7 @@ static struct sx mac_policy_sx; /* Sleeping entry points. */ struct mac_policy_list_head mac_policy_list; struct mac_policy_list_head mac_static_policy_list; +u_int mac_policy_count; /* Registered policy count. */ static void mac_policy_xlock(void); static void mac_policy_xlock_assert(void); @@ -289,8 +290,8 @@ mac_init(void) mac_labelzone_init(); #ifndef MAC_STATIC - rm_init(&mac_policy_rm, "mac_policy_rm"); - sx_init(&mac_policy_sx, "mac_policy_sx"); + rm_init_flags(&mac_policy_rm, "mac_policy_rm", RM_NOWITNESS); + sx_init_flags(&mac_policy_sx, "mac_policy_sx", SX_NOWITNESS); #endif } @@ -351,17 +352,22 @@ mac_policy_getlabeled(struct mac_policy_conf *mpc) * requiring labels across all policies. */ static void -mac_policy_updateflags(void) +mac_policy_update(void) { struct mac_policy_conf *mpc; mac_policy_xlock_assert(); mac_labeled = 0; - LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) + mac_policy_count = 0; + LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { mac_labeled |= mac_policy_getlabeled(mpc); - LIST_FOREACH(mpc, &mac_policy_list, mpc_list) + mac_policy_count++; + } + LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { mac_labeled |= mac_policy_getlabeled(mpc); + mac_policy_count++; + } } static int @@ -434,7 +440,7 @@ mac_policy_register(struct mac_policy_conf *mpc) */ if (mpc->mpc_ops->mpo_init != NULL) (*(mpc->mpc_ops->mpo_init))(mpc); - mac_policy_updateflags(); + mac_policy_update(); SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0); printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, @@ -480,7 +486,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc) LIST_REMOVE(mpc, mpc_list); mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; - mac_policy_updateflags(); + mac_policy_update(); mac_policy_xunlock(); SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0); diff --git a/sys/security/mac/mac_inet.c b/sys/security/mac/mac_inet.c index fd2c629..5753bb6 100644 --- a/sys/security/mac/mac_inet.c +++ b/sys/security/mac/mac_inet.c @@ -193,6 +193,9 @@ mac_ipq_reassemble(struct ipq *q, struct mbuf *m) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(ipq_reassemble, q, q->ipq_label, m, @@ -204,6 +207,9 @@ mac_netinet_fragment(struct mbuf *m, struct mbuf *frag) { struct label *mlabel, *fraglabel; + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); fraglabel = mac_mbuf_to_label(frag); @@ -216,6 +222,9 @@ mac_ipq_create(struct mbuf *m, struct ipq *q) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(ipq_create, m, label, q, q->ipq_label); @@ -227,6 +236,10 @@ mac_inpcb_create_mbuf(struct inpcb *inp, struct mbuf *m) struct label *mlabel; INP_LOCK_ASSERT(inp); + + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(inpcb_create_mbuf, inp, inp->inp_label, m, @@ -239,6 +252,9 @@ mac_ipq_match(struct mbuf *m, struct ipq *q) struct label *label; int result; + if (mac_policy_count == 0) + return (1); + label = mac_mbuf_to_label(m); result = 1; @@ -252,6 +268,9 @@ mac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m) { struct label *mlabel; + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); MAC_IFNET_LOCK(ifp); @@ -265,6 +284,9 @@ mac_netinet_icmp_reply(struct mbuf *mrecv, struct mbuf *msend) { struct label *mrecvlabel, *msendlabel; + if (mac_policy_count == 0) + return; + mrecvlabel = mac_mbuf_to_label(mrecv); msendlabel = mac_mbuf_to_label(msend); @@ -277,6 +299,9 @@ mac_netinet_icmp_replyinplace(struct mbuf *m) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(netinet_icmp_replyinplace, m, label); @@ -287,6 +312,9 @@ mac_netinet_igmp_send(struct ifnet *ifp, struct mbuf *m) { struct label *mlabel; + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); MAC_IFNET_LOCK(ifp); @@ -300,6 +328,9 @@ mac_netinet_tcp_reply(struct mbuf *m) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(netinet_tcp_reply, m, label); @@ -310,6 +341,9 @@ mac_ipq_update(struct mbuf *m, struct ipq *q) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(ipq_update, m, label, q, q->ipq_label); @@ -326,6 +360,9 @@ mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m) M_ASSERTPKTHDR(m); + if (mac_policy_count == 0) + return (0); + label = mac_mbuf_to_label(m); MAC_POLICY_CHECK_NOSLEEP(inpcb_check_deliver, inp, inp->inp_label, m, @@ -371,6 +408,9 @@ mac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend) M_ASSERTPKTHDR(mrecv); M_ASSERTPKTHDR(msend); + if (mac_policy_count == 0) + return; + mrecvlabel = mac_mbuf_to_label(mrecv); msendlabel = mac_mbuf_to_label(msend); @@ -385,6 +425,9 @@ mac_netinet_firewall_send(struct mbuf *m) M_ASSERTPKTHDR(m); + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(netinet_firewall_send, m, label); @@ -455,6 +498,9 @@ mac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m) M_ASSERTPKTHDR(m); + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(syncache_create_mbuf, sc_label, m, diff --git a/sys/security/mac/mac_inet6.c b/sys/security/mac/mac_inet6.c index be26a9d..a080a74 100644 --- a/sys/security/mac/mac_inet6.c +++ b/sys/security/mac/mac_inet6.c @@ -118,6 +118,9 @@ mac_ip6q_reassemble(struct ip6q *q6, struct mbuf *m) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(ip6q_reassemble, q6, q6->ip6q_label, m, @@ -129,6 +132,9 @@ mac_ip6q_create(struct mbuf *m, struct ip6q *q6) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(ip6q_create, m, label, q6, @@ -141,6 +147,9 @@ mac_ip6q_match(struct mbuf *m, struct ip6q *q6) struct label *label; int result; + if (mac_policy_count == 0) + return (1); + label = mac_mbuf_to_label(m); result = 1; @@ -155,6 +164,9 @@ mac_ip6q_update(struct mbuf *m, struct ip6q *q6) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(ip6q_update, m, label, q6, @@ -166,6 +178,9 @@ mac_netinet6_nd6_send(struct ifnet *ifp, struct mbuf *m) { struct label *mlabel; + if (mac_policy_count == 0) + return; + mlabel = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(netinet6_nd6_send, ifp, ifp->if_label, m, diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h index 45bd524..39fc404 100644 --- a/sys/security/mac/mac_internal.h +++ b/sys/security/mac/mac_internal.h @@ -189,6 +189,7 @@ struct label { */ extern struct mac_policy_list_head mac_policy_list; extern struct mac_policy_list_head mac_static_policy_list; +extern u_int mac_policy_count; extern uint64_t mac_labeled; extern struct mtx mac_ifnet_mtx; diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c index ecd4195..ed33885 100644 --- a/sys/security/mac/mac_net.c +++ b/sys/security/mac/mac_net.c @@ -258,6 +258,9 @@ mac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to) { struct label *src_label, *dest_label; + if (mac_policy_count == 0) + return; + src_label = mac_mbuf_to_label(m_from); dest_label = mac_mbuf_to_label(m_to); @@ -296,6 +299,9 @@ void mac_ifnet_create(struct ifnet *ifp) { + if (mac_policy_count == 0) + return; + MAC_IFNET_LOCK(ifp); MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, ifp->if_label); MAC_IFNET_UNLOCK(ifp); @@ -315,6 +321,9 @@ mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m) BPFD_LOCK_ASSERT(d); + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m, @@ -326,6 +335,9 @@ mac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m) { struct label *label; + if (mac_policy_count == 0) + return; + label = mac_mbuf_to_label(m); MAC_IFNET_LOCK(ifp); @@ -344,6 +356,9 @@ mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp) BPFD_LOCK_ASSERT(d); + if (mac_policy_count == 0) + return (0); + MAC_IFNET_LOCK(ifp); MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp, ifp->if_label); @@ -364,6 +379,9 @@ mac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m) M_ASSERTPKTHDR(m); + if (mac_policy_count == 0) + return (0); + label = mac_mbuf_to_label(m); MAC_IFNET_LOCK(ifp); diff --git a/sys/security/mac/mac_socket.c b/sys/security/mac/mac_socket.c index 25f8dae..11d5e05 100644 --- a/sys/security/mac/mac_socket.c +++ b/sys/security/mac/mac_socket.c @@ -88,6 +88,16 @@ __FBSDID("$FreeBSD$"); * remote socket for UNIX domain sockets rather than keeping a local copy on * this endpoint, but be cached and updated based on packets received for * TCP/IP. + * + * Unlike with many other object types, the lock protecting MAC labels on + * sockets (the socket lock) is not frequently held at the points in code + * where socket-related checks are called. The MAC Framework acquires the + * lock over some entry points in order to enforce atomicity (such as label + * copies) but in other cases the policy modules will have to acquire the + * lock themselves if they use labels. This approach (a) avoids lock + * acquisitions when policies don't require labels and (b) solves a number of + * potential lock order issues when multiple sockets are used in the same + * entry point. */ struct label * @@ -234,8 +244,6 @@ void mac_socket_newconn(struct socket *oldso, struct socket *newso) { - SOCK_LOCK_ASSERT(oldso); - MAC_POLICY_PERFORM_NOSLEEP(socket_newconn, oldso, oldso->so_label, newso, newso->so_label); } @@ -256,7 +264,8 @@ mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so) { struct label *label; - SOCK_LOCK_ASSERT(so); + if (mac_policy_count == 0) + return; label = mac_mbuf_to_label(m); @@ -267,12 +276,10 @@ mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so) void mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso) { + + if (mac_policy_count == 0) + return; - /* - * XXXRW: only hold the socket lock on one at a time, as one socket - * is the original, and one is the new. However, it's called in both - * directions, so we can't assert the lock here currently. - */ MAC_POLICY_PERFORM_NOSLEEP(socketpeer_set_from_socket, oldso, oldso->so_label, newso, newso->so_peerlabel); } @@ -282,7 +289,8 @@ mac_socket_create_mbuf(struct socket *so, struct mbuf *m) { struct label *label; - SOCK_LOCK_ASSERT(so); + if (mac_policy_count == 0) + return; label = mac_mbuf_to_label(m); @@ -298,8 +306,6 @@ mac_socket_check_accept(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_accept, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_accept, error, cred, so); @@ -316,8 +322,6 @@ mac_socket_check_bind(struct ucred *cred, struct socket *so, { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_bind, cred, so, so->so_label, sa); MAC_CHECK_PROBE3(socket_check_bind, error, cred, so, sa); @@ -334,8 +338,6 @@ mac_socket_check_connect(struct ucred *cred, struct socket *so, { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_connect, cred, so, so->so_label, sa); MAC_CHECK_PROBE3(socket_check_connect, error, cred, so, sa); @@ -368,7 +370,8 @@ mac_socket_check_deliver(struct socket *so, struct mbuf *m) struct label *label; int error; - SOCK_LOCK_ASSERT(so); + if (mac_policy_count == 0) + return (0); label = mac_mbuf_to_label(m); @@ -387,8 +390,6 @@ mac_socket_check_listen(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_listen, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_listen, error, cred, so); @@ -404,8 +405,6 @@ mac_socket_check_poll(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_poll, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_poll, error, cred, so); @@ -420,8 +419,6 @@ mac_socket_check_receive(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_receive, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_receive, error, cred, so); @@ -455,8 +452,6 @@ mac_socket_check_send(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_send, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_send, error, cred, so); @@ -471,8 +466,6 @@ mac_socket_check_stat(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_stat, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_stat, error, cred, so); @@ -487,8 +480,6 @@ mac_socket_check_visible(struct ucred *cred, struct socket *so) { int error; - SOCK_LOCK_ASSERT(so); - MAC_POLICY_CHECK_NOSLEEP(socket_check_visible, cred, so, so->so_label); MAC_CHECK_PROBE2(socket_check_visible, error, cred, so); diff --git a/sys/security/mac_biba/mac_biba.c b/sys/security/mac_biba/mac_biba.c index 97c3cbe..2c6ada1 100644 --- a/sys/security/mac_biba/mac_biba.c +++ b/sys/security/mac_biba/mac_biba.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson + * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson * Copyright (c) 2001-2005 McAfee, Inc. * Copyright (c) 2006 SPARTA, Inc. * All rights reserved. @@ -125,7 +125,7 @@ SYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW, &ptys_equal, 0, "Label pty devices as biba/equal on create"); TUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal); -static int interfaces_equal; +static int interfaces_equal = 1; SYSCTL_INT(_security_mac_biba, OID_AUTO, interfaces_equal, CTLFLAG_RW, &interfaces_equal, 0, "Label network interfaces as biba/equal on create"); TUNABLE_INT("security.mac.biba.interfaces_equal", &interfaces_equal); @@ -1177,7 +1177,9 @@ biba_inpcb_create(struct socket *so, struct label *solabel, source = SLOT(solabel); dest = SLOT(inplabel); + SOCK_LOCK(so); biba_copy_effective(source, dest); + SOCK_UNLOCK(so); } static void @@ -1198,6 +1200,8 @@ biba_inpcb_sosetlabel(struct socket *so, struct label *solabel, { struct mac_biba *source, *dest; + SOCK_LOCK_ASSERT(so); + source = SLOT(solabel); dest = SLOT(inplabel); @@ -1918,6 +1922,7 @@ biba_socket_check_deliver(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { struct mac_biba *p, *s; + int error; if (!biba_enabled) return (0); @@ -1925,7 +1930,10 @@ biba_socket_check_deliver(struct socket *so, struct label *solabel, p = SLOT(mlabel); s = SLOT(solabel); - return (biba_equal_effective(p, s) ? 0 : EACCES); + SOCK_LOCK(so); + error = biba_equal_effective(p, s) ? 0 : EACCES; + SOCK_UNLOCK(so); + return (error); } static int @@ -1935,6 +1943,8 @@ biba_socket_check_relabel(struct ucred *cred, struct socket *so, struct mac_biba *subj, *obj, *new; int error; + SOCK_LOCK_ASSERT(so); + new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(solabel); @@ -1991,8 +2001,12 @@ biba_socket_check_visible(struct ucred *cred, struct socket *so, subj = SLOT(cred->cr_label); obj = SLOT(solabel); - if (!biba_dominate_effective(obj, subj)) + SOCK_LOCK(so); + if (!biba_dominate_effective(obj, subj)) { + SOCK_UNLOCK(so); return (ENOENT); + } + SOCK_UNLOCK(so); return (0); } @@ -2018,19 +2032,26 @@ biba_socket_create_mbuf(struct socket *so, struct label *solabel, source = SLOT(solabel); dest = SLOT(mlabel); + SOCK_LOCK(so); biba_copy_effective(source, dest); + SOCK_UNLOCK(so); } static void biba_socket_newconn(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsolabel) { - struct mac_biba *source, *dest; + struct mac_biba source, *dest; + + SOCK_LOCK(oldso); + source = *SLOT(oldsolabel); + SOCK_UNLOCK(oldso); - source = SLOT(oldsolabel); dest = SLOT(newsolabel); - biba_copy_effective(source, dest); + SOCK_LOCK(newso); + biba_copy_effective(&source, dest); + SOCK_UNLOCK(newso); } static void @@ -2039,6 +2060,8 @@ biba_socket_relabel(struct ucred *cred, struct socket *so, { struct mac_biba *source, *dest; + SOCK_LOCK_ASSERT(so); + source = SLOT(newlabel); dest = SLOT(solabel); @@ -2054,7 +2077,9 @@ biba_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, source = SLOT(mlabel); dest = SLOT(sopeerlabel); + SOCK_LOCK(so); biba_copy_effective(source, dest); + SOCK_UNLOCK(so); } static void @@ -2062,12 +2087,16 @@ biba_socketpeer_set_from_socket(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsopeerlabel) { - struct mac_biba *source, *dest; + struct mac_biba source, *dest; - source = SLOT(oldsolabel); + SOCK_LOCK(oldso); + source = *SLOT(oldsolabel); + SOCK_UNLOCK(oldso); dest = SLOT(newsopeerlabel); - biba_copy_effective(source, dest); + SOCK_LOCK(newso); + biba_copy_effective(&source, dest); + SOCK_UNLOCK(newso); } static void diff --git a/sys/security/mac_lomac/mac_lomac.c b/sys/security/mac_lomac/mac_lomac.c index ab41c0a..2359b42 100644 --- a/sys/security/mac_lomac/mac_lomac.c +++ b/sys/security/mac_lomac/mac_lomac.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson + * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. * Copyright (c) 2006 SPARTA, Inc. * All rights reserved. @@ -1315,6 +1315,8 @@ lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel, { struct mac_lomac *source, *dest; + SOCK_LOCK_ASSERT(so); + source = SLOT(solabel); dest = SLOT(inplabel); @@ -1930,6 +1932,7 @@ lomac_socket_check_deliver(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { struct mac_lomac *p, *s; + int error; if (!lomac_enabled) return (0); @@ -1937,7 +1940,10 @@ lomac_socket_check_deliver(struct socket *so, struct label *solabel, p = SLOT(mlabel); s = SLOT(solabel); - return (lomac_equal_single(p, s) ? 0 : EACCES); + SOCK_LOCK(so); + error = lomac_equal_single(p, s) ? 0 : EACCES; + SOCK_UNLOCK(so); + return (error); } static int @@ -1947,6 +1953,8 @@ lomac_socket_check_relabel(struct ucred *cred, struct socket *so, struct mac_lomac *subj, *obj, *new; int error; + SOCK_LOCK_ASSERT(so); + new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(solabel); @@ -2003,8 +2011,12 @@ lomac_socket_check_visible(struct ucred *cred, struct socket *so, subj = SLOT(cred->cr_label); obj = SLOT(solabel); - if (!lomac_dominate_single(obj, subj)) + SOCK_LOCK(so); + if (!lomac_dominate_single(obj, subj)) { + SOCK_UNLOCK(so); return (ENOENT); + } + SOCK_UNLOCK(so); return (0); } @@ -2030,19 +2042,26 @@ lomac_socket_create_mbuf(struct socket *so, struct label *solabel, source = SLOT(solabel); dest = SLOT(mlabel); + SOCK_LOCK(so); lomac_copy_single(source, dest); + SOCK_UNLOCK(so); } static void lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsolabel) { - struct mac_lomac *source, *dest; + struct mac_lomac source, *dest; + + SOCK_LOCK(oldso); + source = *SLOT(oldsolabel); + SOCK_UNLOCK(oldso); - source = SLOT(oldsolabel); dest = SLOT(newsolabel); - lomac_copy_single(source, dest); + SOCK_LOCK(newso); + lomac_copy_single(&source, dest); + SOCK_UNLOCK(newso); } static void @@ -2051,6 +2070,8 @@ lomac_socket_relabel(struct ucred *cred, struct socket *so, { struct mac_lomac *source, *dest; + SOCK_LOCK_ASSERT(so); + source = SLOT(newlabel); dest = SLOT(solabel); @@ -2066,7 +2087,9 @@ lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, source = SLOT(mlabel); dest = SLOT(sopeerlabel); + SOCK_LOCK(so); lomac_copy_single(source, dest); + SOCK_UNLOCK(so); } static void @@ -2074,12 +2097,17 @@ lomac_socketpeer_set_from_socket(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsopeerlabel) { - struct mac_lomac *source, *dest; + struct mac_lomac source, *dest; + + SOCK_LOCK(oldso); + source = *SLOT(oldsolabel); + SOCK_UNLOCK(oldso); - source = SLOT(oldsolabel); dest = SLOT(newsopeerlabel); - lomac_copy_single(source, dest); + SOCK_LOCK(newso); + lomac_copy_single(&source, dest); + SOCK_UNLOCK(newso); } static void diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c index 6d13505..a0669c7 100644 --- a/sys/security/mac_mls/mac_mls.c +++ b/sys/security/mac_mls/mac_mls.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson + * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson * Copyright (c) 2001-2005 McAfee, Inc. * Copyright (c) 2006 SPARTA, Inc. * All rights reserved. @@ -1116,6 +1116,8 @@ mls_inpcb_sosetlabel(struct socket *so, struct label *solabel, { struct mac_mls *source, *dest; + SOCK_LOCK_ASSERT(so); + source = SLOT(solabel); dest = SLOT(inplabel); @@ -1623,6 +1625,7 @@ mls_socket_check_deliver(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { struct mac_mls *p, *s; + int error; if (!mls_enabled) return (0); @@ -1630,7 +1633,11 @@ mls_socket_check_deliver(struct socket *so, struct label *solabel, p = SLOT(mlabel); s = SLOT(solabel); - return (mls_equal_effective(p, s) ? 0 : EACCES); + SOCK_LOCK(so); + error = mls_equal_effective(p, s) ? 0 : EACCES; + SOCK_UNLOCK(so); + + return (error); } static int @@ -1640,6 +1647,8 @@ mls_socket_check_relabel(struct ucred *cred, struct socket *so, struct mac_mls *subj, *obj, *new; int error; + SOCK_LOCK_ASSERT(so); + new = SLOT(newlabel); subj = SLOT(cred->cr_label); obj = SLOT(solabel); @@ -1696,8 +1705,12 @@ mls_socket_check_visible(struct ucred *cred, struct socket *so, subj = SLOT(cred->cr_label); obj = SLOT(solabel); - if (!mls_dominate_effective(subj, obj)) + SOCK_LOCK(so); + if (!mls_dominate_effective(subj, obj)) { + SOCK_UNLOCK(so); return (ENOENT); + } + SOCK_UNLOCK(so); return (0); } @@ -1723,19 +1736,26 @@ mls_socket_create_mbuf(struct socket *so, struct label *solabel, source = SLOT(solabel); dest = SLOT(mlabel); + SOCK_LOCK(so); mls_copy_effective(source, dest); + SOCK_UNLOCK(so); } static void mls_socket_newconn(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsolabel) { - struct mac_mls *source, *dest; + struct mac_mls source, *dest; + + SOCK_LOCK(oldso); + source = *SLOT(oldsolabel); + SOCK_UNLOCK(oldso); - source = SLOT(oldsolabel); dest = SLOT(newsolabel); - mls_copy_effective(source, dest); + SOCK_LOCK(newso); + mls_copy_effective(&source, dest); + SOCK_UNLOCK(newso); } static void @@ -1744,6 +1764,8 @@ mls_socket_relabel(struct ucred *cred, struct socket *so, { struct mac_mls *source, *dest; + SOCK_LOCK_ASSERT(so); + source = SLOT(newlabel); dest = SLOT(solabel); @@ -1759,7 +1781,9 @@ mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, source = SLOT(mlabel); dest = SLOT(sopeerlabel); + SOCK_LOCK(so); mls_copy_effective(source, dest); + SOCK_UNLOCK(so); } static void @@ -1767,12 +1791,17 @@ mls_socketpeer_set_from_socket(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsopeerlabel) { - struct mac_mls *source, *dest; + struct mac_mls source, *dest; + + SOCK_LOCK(oldso); + source = *SLOT(oldsolabel); + SOCK_UNLOCK(oldso); - source = SLOT(oldsolabel); dest = SLOT(newsopeerlabel); - mls_copy_effective(source, dest); + SOCK_LOCK(newso); + mls_copy_effective(&source, dest); + SOCK_UNLOCK(newso); } static void diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c index cecf2ea..007efb8 100644 --- a/sys/security/mac_stub/mac_stub.c +++ b/sys/security/mac_stub/mac_stub.c @@ -413,6 +413,8 @@ stub_inpcb_sosetlabel(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { + SOCK_LOCK_ASSERT(so); + } static void @@ -809,6 +811,11 @@ stub_socket_check_accept(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -817,6 +824,11 @@ stub_socket_check_bind(struct ucred *cred, struct socket *so, struct label *solabel, struct sockaddr *sa) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -825,6 +837,11 @@ stub_socket_check_connect(struct ucred *cred, struct socket *so, struct label *solabel, struct sockaddr *sa) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -840,6 +857,11 @@ stub_socket_check_deliver(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -848,6 +870,11 @@ stub_socket_check_listen(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -856,6 +883,11 @@ stub_socket_check_poll(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -864,6 +896,11 @@ stub_socket_check_receive(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -872,6 +909,8 @@ stub_socket_check_relabel(struct ucred *cred, struct socket *so, struct label *solabel, struct label *newlabel) { + SOCK_LOCK_ASSERT(so); + return (0); } static int @@ -879,6 +918,11 @@ stub_socket_check_send(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -887,6 +931,11 @@ stub_socket_check_stat(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -903,6 +952,11 @@ stub_socket_check_visible(struct ucred *cred, struct socket *so, struct label *solabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif + return (0); } @@ -918,6 +972,10 @@ stub_socket_create_mbuf(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif } static void @@ -925,6 +983,14 @@ stub_socket_newconn(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsolabel) { +#if 0 + SOCK_LOCK(oldso); + SOCK_UNLOCK(oldso); +#endif +#if 0 + SOCK_LOCK(newso); + SOCK_UNLOCK(newso); +#endif } static void @@ -932,6 +998,7 @@ stub_socket_relabel(struct ucred *cred, struct socket *so, struct label *solabel, struct label *newlabel) { + SOCK_LOCK_ASSERT(so); } static void @@ -939,6 +1006,10 @@ stub_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, struct socket *so, struct label *sopeerlabel) { +#if 0 + SOCK_LOCK(so); + SOCK_UNLOCK(so); +#endif } static void @@ -947,6 +1018,14 @@ stub_socketpeer_set_from_socket(struct socket *oldso, struct label *newsopeerlabel) { +#if 0 + SOCK_LOCK(oldso); + SOCK_UNLOCK(oldso); +#endif +#if 0 + SOCK_LOCK(newso); + SOCK_UNLOCK(newso); +#endif } static void diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c index 20ca542..bef0cb7 100644 --- a/sys/security/mac_test/mac_test.c +++ b/sys/security/mac_test/mac_test.c @@ -671,7 +671,9 @@ test_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); LABEL_CHECK(inplabel, MAGIC_INPCB); COUNTER_INC(inpcb_create); } @@ -717,6 +719,8 @@ test_inpcb_sosetlabel(struct socket *so, struct label *solabel, struct inpcb *inp, struct label *inplabel) { + SOCK_LOCK_ASSERT(so); + LABEL_CHECK(solabel, MAGIC_SOCKET); LABEL_CHECK(inplabel, MAGIC_INPCB); COUNTER_INC(inpcb_sosetlabel); @@ -1526,7 +1530,9 @@ test_socket_check_accept(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_accept); return (0); @@ -1539,7 +1545,9 @@ test_socket_check_bind(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_bind); return (0); @@ -1552,7 +1560,9 @@ test_socket_check_connect(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_connect); return (0); @@ -1564,7 +1574,9 @@ test_socket_check_deliver(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); LABEL_CHECK(mlabel, MAGIC_MBUF); COUNTER_INC(socket_check_deliver); @@ -1578,7 +1590,9 @@ test_socket_check_listen(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_listen); return (0); @@ -1591,7 +1605,9 @@ test_socket_check_poll(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_poll); return (0); @@ -1604,7 +1620,9 @@ test_socket_check_receive(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_receive); return (0); @@ -1616,6 +1634,8 @@ test_socket_check_relabel(struct ucred *cred, struct socket *so, struct label *solabel, struct label *newlabel) { + SOCK_LOCK_ASSERT(so); + LABEL_CHECK(cred->cr_label, MAGIC_CRED); LABEL_CHECK(solabel, MAGIC_SOCKET); LABEL_CHECK(newlabel, MAGIC_SOCKET); @@ -1631,7 +1651,9 @@ test_socket_check_send(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_send); return (0); @@ -1644,7 +1666,9 @@ test_socket_check_stat(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_stat); return (0); @@ -1657,7 +1681,9 @@ test_socket_check_visible(struct ucred *cred, struct socket *so, { LABEL_CHECK(cred->cr_label, MAGIC_CRED); + SOCK_LOCK(so); LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socket_check_visible); return (0); @@ -1686,11 +1712,13 @@ test_socket_create(struct ucred *cred, struct socket *so, COUNTER_DECL(socket_create_mbuf); static void -test_socket_create_mbuf(struct socket *so, struct label *socketlabel, +test_socket_create_mbuf(struct socket *so, struct label *solabel, struct mbuf *m, struct label *mlabel) { - LABEL_CHECK(socketlabel, MAGIC_SOCKET); + SOCK_LOCK(so); + LABEL_CHECK(solabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); LABEL_CHECK(mlabel, MAGIC_MBUF); COUNTER_INC(socket_create_mbuf); } @@ -1749,8 +1777,12 @@ test_socket_newconn(struct socket *oldso, struct label *oldsolabel, struct socket *newso, struct label *newsolabel) { + SOCK_LOCK(oldso); LABEL_CHECK(oldsolabel, MAGIC_SOCKET); + SOCK_UNLOCK(oldso); + SOCK_LOCK(newso); LABEL_CHECK(newsolabel, MAGIC_SOCKET); + SOCK_UNLOCK(newso); COUNTER_INC(socket_newconn); } @@ -1760,6 +1792,8 @@ test_socket_relabel(struct ucred *cred, struct socket *so, struct label *solabel, struct label *newlabel) { + SOCK_LOCK_ASSERT(so); + LABEL_CHECK(cred->cr_label, MAGIC_CRED); LABEL_CHECK(solabel, MAGIC_SOCKET); LABEL_CHECK(newlabel, MAGIC_SOCKET); @@ -1805,11 +1839,13 @@ test_socketpeer_init_label(struct label *label, int flag) COUNTER_DECL(socketpeer_set_from_mbuf); static void test_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, - struct socket *socket, struct label *socketpeerlabel) + struct socket *so, struct label *sopeerlabel) { LABEL_CHECK(mlabel, MAGIC_MBUF); - LABEL_CHECK(socketpeerlabel, MAGIC_SOCKET); + SOCK_LOCK(so); + LABEL_CHECK(sopeerlabel, MAGIC_SOCKET); + SOCK_UNLOCK(so); COUNTER_INC(socketpeer_set_from_mbuf); } @@ -1820,8 +1856,12 @@ test_socketpeer_set_from_socket(struct socket *oldso, struct label *newsopeerlabel) { + SOCK_LOCK(oldso); LABEL_CHECK(oldsolabel, MAGIC_SOCKET); + SOCK_UNLOCK(oldso); + SOCK_LOCK(newso); LABEL_CHECK(newsopeerlabel, MAGIC_SOCKET); + SOCK_UNLOCK(newso); COUNTER_INC(socketpeer_set_from_socket); } diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC index a3dad1c..943dc74 100644 --- a/sys/sparc64/conf/GENERIC +++ b/sys/sparc64/conf/GENERIC @@ -65,6 +65,7 @@ options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing +options MAC # TrustedBSD MAC Framework # Debugging for use in -current options KDB # Enable kernel debugger support. diff --git a/sys/sparc64/conf/MAC b/sys/sparc64/conf/MAC deleted file mode 100644 index 56af83d..0000000 --- a/sys/sparc64/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/sparc64 MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/sun4v/conf/GENERIC b/sys/sun4v/conf/GENERIC index 2291087..438db17 100644 --- a/sys/sun4v/conf/GENERIC +++ b/sys/sun4v/conf/GENERIC @@ -66,6 +66,7 @@ options AHC_REG_PRETTY_PRINT # Print register bitfields in debug options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing +options MAC # TrustedBSD MAC Framework # Debugging for use in -current options KDB # Enable kernel debugger support. diff --git a/sys/sun4v/conf/MAC b/sys/sun4v/conf/MAC deleted file mode 100644 index 56af83d..0000000 --- a/sys/sun4v/conf/MAC +++ /dev/null @@ -1,28 +0,0 @@ -# MAC -- Generic kernel configuration file for FreeBSD/sparc64 MAC -# -# The Mandatory Access Control, or MAC, framework allows administrators to -# finely control system security by providing for a loadable security pol- -# icy architecture. -# -# For more information see: -# -# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html -# -# $FreeBSD$ - -include GENERIC -ident MAC - -options MAC - -#options MAC_BIBA # BIBA data integrity policy -#options MAC_BSDEXTENDED # File system firewall policy -#options MAC_IFOFF # Network interface silencing policy -#options MAC_LOMAC # Low-watermark data integrity policy -#options MAC_MLS # Multi-level confidentiality policy -#options MAC_NONE # NULL policy -#options MAC_PARTITION # Process partition policy -#options MAC_PORTACL # Network port access control policy -#options MAC_SEEOTHERUIDS # UID visibility policy -#options MAC_STUB # Stub policy -#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/sun4v/include/pcpu.h b/sys/sun4v/include/pcpu.h index 434f1cd..ec89212 100644 --- a/sys/sun4v/include/pcpu.h +++ b/sys/sun4v/include/pcpu.h @@ -39,9 +39,9 @@ struct pmap; #ifdef KTR -#define PCPU_MD_FIELDS_PAD (4 - (PCPU_NAME_LEN + 7) / 8) +#define PCPU_MD_FIELDS_PAD (3 - (PCPU_NAME_LEN + 7) / 8) #else -#define PCPU_MD_FIELDS_PAD 4 +#define PCPU_MD_FIELDS_PAD 3 #endif /* diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index 2be03d1..68d7df0 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -709,11 +709,6 @@ struct pmc { * array. The size of this structure is thus PMC architecture * dependent. * - * TODO: Only process-private counting mode PMCs may be attached to a - * process different from the allocator process (since we do not have - * the infrastructure to make sense of an interrupted PC value from a - * 'target' process (yet)). - * */ struct pmc_targetstate { diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 3feae69..1e19bb6 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -419,7 +419,7 @@ extern struct vattr va_null; /* predefined null vattr structure */ #define VI_MTX(vp) (&(vp)->v_interlock) #define VN_LOCK_AREC(vp) \ - ((vp)->v_vnlock->lock_object.lo_flags |= LK_CANRECURSE) + ((vp)->v_vnlock->lock_object.lo_flags |= LO_RECURSABLE) #define VN_LOCK_ASHARE(vp) \ ((vp)->v_vnlock->lock_object.lo_flags &= ~LK_NOSHARE) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 5d959ac4..195df44 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -556,8 +556,8 @@ MTX_SYSINIT(softdep_lock, &lk, "Softdep Lock", MTX_DEF); #define ACQUIRE_LOCK(lk) mtx_lock(lk) #define FREE_LOCK(lk) mtx_unlock(lk) -#define BUF_AREC(bp) ((bp)->b_lock.lock_object.lo_flags |= LK_CANRECURSE) -#define BUF_NOREC(bp) ((bp)->b_lock.lock_object.lo_flags &= ~LK_CANRECURSE) +#define BUF_AREC(bp) ((bp)->b_lock.lock_object.lo_flags |= LO_RECURSABLE) +#define BUF_NOREC(bp) ((bp)->b_lock.lock_object.lo_flags &= ~LO_RECURSABLE) /* * Worklist queue management. diff --git a/sys/ufs/ufs/dirhash.h b/sys/ufs/ufs/dirhash.h index 9778752..e5978b4 100644 --- a/sys/ufs/ufs/dirhash.h +++ b/sys/ufs/ufs/dirhash.h @@ -105,6 +105,8 @@ struct dirhash { int dh_onlist; /* true if on the ufsdirhash_list chain */ + time_t dh_lastused; /* time the dirhash was last read or written*/ + /* Protected by ufsdirhash_mtx. */ TAILQ_ENTRY(dirhash) dh_list; /* chain of all dirhashes */ }; diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index 3b6d5e1..5066326 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$"); #include <sys/refcount.h> #include <sys/sysctl.h> #include <sys/sx.h> +#include <sys/eventhandler.h> +#include <sys/time.h> #include <vm/uma.h> #include <ufs/ufs/quota.h> @@ -81,6 +83,13 @@ SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_mem, CTLFLAG_RD, &ufs_dirhashmem, static int ufs_dirhashcheck = 0; SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_docheck, CTLFLAG_RW, &ufs_dirhashcheck, 0, "enable extra sanity tests"); +static int ufs_dirhashlowmemcount = 0; +SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_lowmemcount, CTLFLAG_RD, + &ufs_dirhashlowmemcount, 0, "number of times low memory hook called"); +static int ufs_dirhashreclaimage = 5; +SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_reclaimage, CTLFLAG_RW, + &ufs_dirhashreclaimage, 0, + "max time in seconds of hash inactivity before deletion in low VM events"); static int ufsdirhash_hash(struct dirhash *dh, char *name, int namelen); @@ -90,6 +99,7 @@ static int ufsdirhash_findslot(struct dirhash *dh, char *name, int namelen, doff_t offset); static doff_t ufsdirhash_getprev(struct direct *dp, doff_t offset); static int ufsdirhash_recycle(int wanted); +static void ufsdirhash_lowmem(void); static void ufsdirhash_free_locked(struct inode *ip); static uma_zone_t ufsdirhash_zone; @@ -393,6 +403,7 @@ ufsdirhash_build(struct inode *ip) dh->dh_seqopt = 0; dh->dh_seqoff = 0; dh->dh_score = DH_SCOREINIT; + dh->dh_lastused = time_second; /* * Use non-blocking mallocs so that we will revert to a linear @@ -569,6 +580,9 @@ ufsdirhash_lookup(struct inode *ip, char *name, int namelen, doff_t *offp, /* Update the score. */ if (dh->dh_score < DH_SCOREMAX) dh->dh_score++; + + /* Update last used time. */ + dh->dh_lastused = time_second; DIRHASHLIST_UNLOCK(); vp = ip->i_vnode; @@ -811,6 +825,9 @@ ufsdirhash_add(struct inode *ip, struct direct *dirp, doff_t offset) dh->dh_hused++; DH_ENTRY(dh, slot) = offset; + /* Update last used time. */ + dh->dh_lastused = time_second; + /* Update the per-block summary info. */ ufsdirhash_adjfree(dh, offset, -DIRSIZ(0, dirp)); ufsdirhash_release(dh); @@ -1150,6 +1167,46 @@ ufsdirhash_getprev(struct direct *dirp, doff_t offset) } /* + * Delete the given dirhash and reclaim its memory. Assumes that + * ufsdirhash_list is locked, and leaves it locked. Also assumes + * that dh is locked. Returns the amount of memory freed. + */ +static int +ufsdirhash_destroy(struct dirhash *dh) +{ + doff_t **hash; + u_int8_t *blkfree; + int i, mem, narrays; + + KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list")); + + /* Remove it from the list and detach its memory. */ + TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list); + dh->dh_onlist = 0; + hash = dh->dh_hash; + dh->dh_hash = NULL; + blkfree = dh->dh_blkfree; + dh->dh_blkfree = NULL; + narrays = dh->dh_narrays; + mem = dh->dh_memreq; + dh->dh_memreq = 0; + + /* Unlock everything, free the detached memory. */ + ufsdirhash_release(dh); + DIRHASHLIST_UNLOCK(); + for (i = 0; i < narrays; i++) + DIRHASH_BLKFREE(hash[i]); + free(hash, M_DIRHASH); + free(blkfree, M_DIRHASH); + + /* Account for the returned memory. */ + DIRHASHLIST_LOCK(); + ufs_dirhashmem -= mem; + + return (mem); +} + +/* * Try to free up `wanted' bytes by stealing memory from existing * dirhashes. Returns zero with list locked if successful. */ @@ -1157,9 +1214,6 @@ static int ufsdirhash_recycle(int wanted) { struct dirhash *dh; - doff_t **hash; - u_int8_t *blkfree; - int i, mem, narrays; DIRHASHLIST_LOCK(); dh = TAILQ_FIRST(&ufsdirhash_list); @@ -1177,36 +1231,59 @@ ufsdirhash_recycle(int wanted) dh = TAILQ_NEXT(dh, dh_list); continue; } - KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list")); - /* Remove it from the list and detach its memory. */ - TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list); - dh->dh_onlist = 0; - hash = dh->dh_hash; - dh->dh_hash = NULL; - blkfree = dh->dh_blkfree; - dh->dh_blkfree = NULL; - narrays = dh->dh_narrays; - mem = dh->dh_memreq; - dh->dh_memreq = 0; - - /* Unlock everything, free the detached memory. */ - ufsdirhash_release(dh); - DIRHASHLIST_UNLOCK(); - for (i = 0; i < narrays; i++) - DIRHASH_BLKFREE(hash[i]); - free(hash, M_DIRHASH); - free(blkfree, M_DIRHASH); - - /* Account for the returned memory, and repeat if necessary. */ - DIRHASHLIST_LOCK(); - ufs_dirhashmem -= mem; + ufsdirhash_destroy(dh); + + /* Repeat if necessary. */ dh = TAILQ_FIRST(&ufsdirhash_list); } /* Success; return with list locked. */ return (0); } +/* + * Callback that frees some dirhashes when the system is low on virtual memory. + */ +static void +ufsdirhash_lowmem() +{ + struct dirhash *dh; + int memfreed = 0; + /* XXX: this 10% may need to be adjusted */ + int memwanted = ufs_dirhashmem / 10; + + ufs_dirhashlowmemcount++; + + DIRHASHLIST_LOCK(); + /* + * Delete dirhashes not used for more than ufs_dirhashreclaimage + * seconds. If we can't get a lock on the dirhash, it will be skipped. + */ + for (dh = TAILQ_FIRST(&ufsdirhash_list); dh != NULL; dh = + TAILQ_NEXT(dh, dh_list)) { + if (!sx_try_xlock(&dh->dh_lock)) + continue; + if (time_second - dh->dh_lastused > ufs_dirhashreclaimage) + memfreed += ufsdirhash_destroy(dh); + /* Unlock if we didn't delete the dirhash */ + else + ufsdirhash_release(dh); + } + + /* + * If not enough memory was freed, keep deleting hashes from the head + * of the dirhash list. The ones closest to the head should be the + * oldest. + */ + for (dh = TAILQ_FIRST(&ufsdirhash_list); memfreed < memwanted && + dh !=NULL; dh = TAILQ_NEXT(dh, dh_list)) { + if (!sx_try_xlock(&dh->dh_lock)) + continue; + memfreed += ufsdirhash_destroy(dh); + } + DIRHASHLIST_UNLOCK(); +} + void ufsdirhash_init() @@ -1215,6 +1292,10 @@ ufsdirhash_init() NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mtx_init(&ufsdirhash_mtx, "dirhash list", NULL, MTX_DEF); TAILQ_INIT(&ufsdirhash_list); + + /* Register a callback function to handle low memory signals */ + EVENTHANDLER_REGISTER(vm_lowmem, ufsdirhash_lowmem, NULL, + EVENTHANDLER_PRI_FIRST); } void diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index ed09044..47177e3 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -403,22 +403,28 @@ vnode_pager_setsize(vp, nsize) pmap_zero_page_area(m, base, size); /* - * Clear out partial-page dirty bits. This - * has the side effect of setting the valid - * bits, but that is ok. There are a bunch - * of places in the VM system where we expected - * m->dirty == VM_PAGE_BITS_ALL. The file EOF - * case is one of them. If the page is still - * partially dirty, make it fully dirty. + * Update the valid bits to reflect the blocks that + * have been zeroed. Some of these valid bits may + * have already been set. + */ + vm_page_set_valid(m, base, size); + + /* + * Round "base" to the next block boundary so that the + * dirty bit for a partially zeroed block is not + * cleared. + */ + base = roundup2(base, DEV_BSIZE); + + /* + * Clear out partial-page dirty bits. * * note that we do not clear out the valid * bits. This would prevent bogus_page * replacement from working properly. */ vm_page_lock_queues(); - vm_page_set_validclean(m, base, size); - if (m->dirty != 0) - m->dirty = VM_PAGE_BITS_ALL; + vm_page_clear_dirty(m, base, PAGE_SIZE - base); vm_page_unlock_queues(); } else if ((nsize & PAGE_MASK) && __predict_false(object->cache != NULL)) { |