mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-26 20:12:44 +00:00
Compare commits
21 Commits
41455061c5
...
f71fe8b0b1
Author | SHA1 | Date | |
---|---|---|---|
|
f71fe8b0b1 | ||
|
f2233ac33a | ||
|
9206c79961 | ||
|
6d77827b96 | ||
|
5317480967 | ||
|
6d4c59e261 | ||
|
2839ad58dd | ||
|
5ac39263d8 | ||
|
5bd08172b4 | ||
|
56b7685ae3 | ||
|
4cc5d081d8 | ||
|
cca0dc49e0 | ||
|
3abef90c32 | ||
|
c0a5ee953f | ||
|
ccb973da1f | ||
|
cab31f5633 | ||
|
5035db222e | ||
|
ae366a1fd4 | ||
|
e640de418e | ||
|
2d05d6a99d | ||
|
ce4ef8642b |
@ -1,3 +1,6 @@
|
||||
.\"-
|
||||
.\" SPDX-License-Identifier: BSD-3-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
@ -25,18 +28,32 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd February 16, 1997
|
||||
.Dd November 17, 2024
|
||||
.Dt INTRO 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm intro
|
||||
.Nd "introduction to file formats"
|
||||
.Nd introduction to file formats
|
||||
.Sh DESCRIPTION
|
||||
This section contains information about file formats.
|
||||
This section contains information about the file formats
|
||||
which comprise most data structures in the
|
||||
.Bx
|
||||
environment, including:
|
||||
.Pp
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
ASCII configuration and resource files
|
||||
.It
|
||||
System binary file and stream structures
|
||||
.It
|
||||
Composition of database files
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/shells -compact
|
||||
.It Pa /etc
|
||||
location of most system configuration files
|
||||
.Bl -tag -width "/usr/local/etc/" -compact
|
||||
.It Pa /etc/
|
||||
location of most base system configuration files
|
||||
.It Pa /usr/local/etc/
|
||||
location of installed component configuration files
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
|
@ -101,14 +101,19 @@ get_vfpcontext(struct thread *td, mcontext_vfp_t *vfp)
|
||||
P_SHOULDSTOP(td->td_proc));
|
||||
|
||||
pcb = td->td_pcb;
|
||||
if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0 && td == curthread) {
|
||||
if (td == curthread) {
|
||||
critical_enter();
|
||||
vfp_store(&pcb->pcb_vfpstate, false);
|
||||
critical_exit();
|
||||
}
|
||||
KASSERT(pcb->pcb_vfpsaved == &pcb->pcb_vfpstate,
|
||||
("Called get_vfpcontext while the kernel is using the VFP"));
|
||||
memcpy(vfp, &pcb->pcb_vfpstate, sizeof(*vfp));
|
||||
|
||||
memset(vfp, 0, sizeof(*vfp));
|
||||
memcpy(vfp->mcv_reg, pcb->pcb_vfpstate.reg,
|
||||
sizeof(vfp->mcv_reg));
|
||||
vfp->mcv_fpscr = pcb->pcb_vfpstate.fpscr;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -127,7 +132,10 @@ set_vfpcontext(struct thread *td, mcontext_vfp_t *vfp)
|
||||
}
|
||||
KASSERT(pcb->pcb_vfpsaved == &pcb->pcb_vfpstate,
|
||||
("Called set_vfpcontext while the kernel is using the VFP"));
|
||||
memcpy(&pcb->pcb_vfpstate, vfp, sizeof(*vfp));
|
||||
memcpy(pcb->pcb_vfpstate.reg, vfp->mcv_reg,
|
||||
sizeof(pcb->pcb_vfpstate.reg));
|
||||
pcb->pcb_vfpstate.fpscr = vfp->mcv_fpscr;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -163,8 +171,6 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
|
||||
{
|
||||
struct trapframe *tf = td->td_frame;
|
||||
__greg_t *gr = mcp->__gregs;
|
||||
mcontext_vfp_t mcontext_vfp;
|
||||
int rv;
|
||||
|
||||
if (clear_ret & GET_MC_CLEAR_RET) {
|
||||
gr[_REG_R0] = 0;
|
||||
@ -189,19 +195,9 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
|
||||
gr[_REG_LR] = tf->tf_usr_lr;
|
||||
gr[_REG_PC] = tf->tf_pc;
|
||||
|
||||
#ifdef VFP
|
||||
if (mcp->mc_vfp_size != sizeof(mcontext_vfp_t))
|
||||
return (EINVAL);
|
||||
get_vfpcontext(td, &mcontext_vfp);
|
||||
#else
|
||||
bzero(&mcontext_vfp, sizeof(mcontext_vfp));
|
||||
#endif
|
||||
|
||||
if (mcp->mc_vfp_ptr != NULL) {
|
||||
rv = copyout(&mcontext_vfp, mcp->mc_vfp_ptr, sizeof(mcontext_vfp));
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
}
|
||||
mcp->mc_vfp_size = 0;
|
||||
mcp->mc_vfp_ptr = NULL;
|
||||
memset(&mcp->mc_spare, 0, sizeof(mcp->mc_spare));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -315,6 +311,16 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||
/* Populate the siginfo frame. */
|
||||
bzero(&frame, sizeof(frame));
|
||||
get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
|
||||
|
||||
#ifdef VFP
|
||||
get_vfpcontext(td, &frame.sf_vfp);
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_size = sizeof(fp->sf_vfp);
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_ptr = &fp->sf_vfp;
|
||||
#else
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_size = 0;
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_ptr = NULL;
|
||||
#endif
|
||||
|
||||
frame.sf_si = ksi->ksi_info;
|
||||
frame.sf_uc.uc_sigmask = *mask;
|
||||
frame.sf_uc.uc_stack = td->td_sigstk;
|
||||
|
@ -158,7 +158,7 @@ SYSCTL_INT(_hw_ena, OID_AUTO, enable_9k_mbufs, CTLFLAG_RDTUN,
|
||||
int ena_force_large_llq_header = ENA_LLQ_HEADER_SIZE_POLICY_DEFAULT;
|
||||
SYSCTL_INT(_hw_ena, OID_AUTO, force_large_llq_header, CTLFLAG_RDTUN,
|
||||
&ena_force_large_llq_header, 0,
|
||||
"Change default LLQ entry size received from the device\n");
|
||||
"Change default LLQ entry size received from the device");
|
||||
|
||||
int ena_rss_table_size = ENA_RX_RSS_TABLE_SIZE;
|
||||
|
||||
|
@ -122,6 +122,7 @@ struct hms_softc {
|
||||
hid_size_t isize;
|
||||
uint32_t drift_cnt;
|
||||
uint32_t drift_thresh;
|
||||
struct hid_location wheel_loc;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -131,6 +132,7 @@ hms_intr(void *context, void *buf, hid_size_t len)
|
||||
{
|
||||
struct hidmap *hm = context;
|
||||
struct hms_softc *sc = device_get_softc(hm->dev);
|
||||
int32_t wheel;
|
||||
|
||||
if (len > sc->isize)
|
||||
len = sc->isize;
|
||||
@ -140,8 +142,18 @@ hms_intr(void *context, void *buf, hid_size_t len)
|
||||
* to return last report data in sampling mode even after touch has
|
||||
* been ended. That results in cursor drift. Filter out such a
|
||||
* reports through comparing with previous one.
|
||||
*
|
||||
* Except this results in dropping consecutive mouse wheel events,
|
||||
* because differently from cursor movement they always move by the
|
||||
* same amount. So, don't do it when there's mouse wheel movement.
|
||||
*/
|
||||
if (len == sc->last_irsize && memcmp(buf, sc->last_ir, len) == 0) {
|
||||
if (sc->wheel_loc.size != 0)
|
||||
wheel = hid_get_data(buf, len, &sc->wheel_loc);
|
||||
else
|
||||
wheel = 0;
|
||||
|
||||
if (len == sc->last_irsize && memcmp(buf, sc->last_ir, len) == 0 &&
|
||||
wheel == 0) {
|
||||
sc->drift_cnt++;
|
||||
if (sc->drift_thresh != 0 && sc->drift_cnt >= sc->drift_thresh)
|
||||
return;
|
||||
@ -285,9 +297,25 @@ hms_attach(device_t dev)
|
||||
/* Count number of input usages of variable type mapped to buttons */
|
||||
for (hi = sc->hm.hid_items;
|
||||
hi < sc->hm.hid_items + sc->hm.nhid_items;
|
||||
hi++)
|
||||
hi++) {
|
||||
if (hi->type == HIDMAP_TYPE_VARIABLE && hi->evtype == EV_KEY)
|
||||
nbuttons++;
|
||||
#ifdef IICHID_SAMPLING
|
||||
/*
|
||||
* Make note of which part of the report descriptor is the wheel.
|
||||
*/
|
||||
if (hi->type == HIDMAP_TYPE_VARIABLE &&
|
||||
hi->evtype == EV_REL && hi->code == REL_WHEEL) {
|
||||
sc->wheel_loc = hi->loc;
|
||||
/*
|
||||
* Account for the leading Report ID byte
|
||||
* if it is a multi-report device.
|
||||
*/
|
||||
if (hi->id != 0)
|
||||
sc->wheel_loc.pos += 8;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* announce information about the mouse */
|
||||
device_printf(dev, "%d buttons and [%s%s%s%s%s] coordinates ID=%u\n",
|
||||
|
@ -3404,6 +3404,51 @@ mlx5e_set_rx_mode(if_t ifp)
|
||||
queue_work(priv->wq, &priv->set_rx_mode_work);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_ipsec_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef IPSEC_OFFLOAD
|
||||
if ((mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD) != 0)
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_ratelimit_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef RATELIMIT
|
||||
if (MLX5_CAP_GEN(mdev, qos) &&
|
||||
MLX5_CAP_QOS(mdev, packet_pacing))
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_tlstx_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef KERN_TLS
|
||||
if (MLX5_CAP_GEN(mdev, tls_tx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0)
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_tlsrx_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef KERN_TLS
|
||||
if (MLX5_CAP_GEN(mdev, tls_rx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0 &&
|
||||
MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
|
||||
ft_field_support.outer_ip_version) != 0)
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5e_ioctl(if_t ifp, u_long command, caddr_t data)
|
||||
{
|
||||
@ -3507,6 +3552,24 @@ mlx5e_ioctl(if_t ifp, u_long command, caddr_t data)
|
||||
drv_ioctl_data = (struct siocsifcapnv_driver_data *)data;
|
||||
PRIV_LOCK(priv);
|
||||
siocsifcap_driver:
|
||||
if (!mlx5e_is_tlstx_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &= ~(IFCAP_TXTLS4 |
|
||||
IFCAP_TXTLS6);
|
||||
}
|
||||
if (!mlx5e_is_tlsrx_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &= ~(
|
||||
IFCAP2_BIT(IFCAP2_RXTLS4) |
|
||||
IFCAP2_BIT(IFCAP2_RXTLS6));
|
||||
}
|
||||
if (!mlx5e_is_ipsec_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &=
|
||||
~IFCAP2_BIT(IFCAP2_IPSEC_OFFLOAD);
|
||||
}
|
||||
if (!mlx5e_is_ratelimit_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &= ~(IFCAP_TXTLS_RTLMT |
|
||||
IFCAP_TXRTLMT);
|
||||
}
|
||||
|
||||
mask = drv_ioctl_data->reqcap ^ if_getcapenable(ifp);
|
||||
|
||||
if (mask & IFCAP_TXCSUM) {
|
||||
@ -4535,29 +4598,20 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev)
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TSO | IFCAP_VLAN_HWTSO, 0);
|
||||
if_setcapabilitiesbit(ifp, IFCAP_HWSTATS | IFCAP_HWRXTSTMP, 0);
|
||||
if_setcapabilitiesbit(ifp, IFCAP_MEXTPG, 0);
|
||||
#ifdef KERN_TLS
|
||||
if (MLX5_CAP_GEN(mdev, tls_tx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0)
|
||||
if (mlx5e_is_tlstx_capable(mdev))
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXTLS4 | IFCAP_TXTLS6, 0);
|
||||
if (MLX5_CAP_GEN(mdev, tls_rx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0 &&
|
||||
MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
|
||||
ft_field_support.outer_ip_version) != 0)
|
||||
if (mlx5e_is_tlsrx_capable(mdev))
|
||||
if_setcapabilities2bit(ifp, IFCAP2_BIT(IFCAP2_RXTLS4) |
|
||||
IFCAP2_BIT(IFCAP2_RXTLS6), 0);
|
||||
#endif
|
||||
#ifdef RATELIMIT
|
||||
if (MLX5_CAP_GEN(mdev, qos) &&
|
||||
MLX5_CAP_QOS(mdev, packet_pacing))
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXRTLMT | IFCAP_TXTLS_RTLMT,
|
||||
0);
|
||||
#endif
|
||||
if (mlx5e_is_ratelimit_capable(mdev)) {
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXRTLMT, 0);
|
||||
if (mlx5e_is_tlstx_capable(mdev))
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXTLS_RTLMT, 0);
|
||||
}
|
||||
if_setcapabilitiesbit(ifp, IFCAP_VXLAN_HWCSUM | IFCAP_VXLAN_HWTSO, 0);
|
||||
#ifdef IPSEC_OFFLOAD
|
||||
if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)
|
||||
if (mlx5e_is_ipsec_capable(mdev))
|
||||
if_setcapabilities2bit(ifp, IFCAP2_BIT(IFCAP2_IPSEC_OFFLOAD),
|
||||
0);
|
||||
#endif
|
||||
|
||||
if_setsndtagallocfn(ifp, mlx5e_snd_tag_alloc);
|
||||
#ifdef RATELIMIT
|
||||
|
@ -67,6 +67,24 @@ struct dummy_softc {
|
||||
struct mtx *lock;
|
||||
};
|
||||
|
||||
static bool
|
||||
dummy_active(struct dummy_softc *sc)
|
||||
{
|
||||
struct dummy_chan *ch;
|
||||
int i;
|
||||
|
||||
snd_mtxassert(sc->lock);
|
||||
|
||||
for (i = 0; i < sc->chnum; i++) {
|
||||
ch = &sc->chans[i];
|
||||
if (ch->run)
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* No channel is running at the moment. */
|
||||
return (false);
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_chan_io(void *arg)
|
||||
{
|
||||
@ -74,7 +92,9 @@ dummy_chan_io(void *arg)
|
||||
struct dummy_chan *ch;
|
||||
int i = 0;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
/* Do not reschedule if no channel is running. */
|
||||
if (!dummy_active(sc))
|
||||
return;
|
||||
|
||||
for (i = 0; i < sc->chnum; i++) {
|
||||
ch = &sc->chans[i];
|
||||
@ -89,8 +109,6 @@ dummy_chan_io(void *arg)
|
||||
snd_mtxlock(sc->lock);
|
||||
}
|
||||
callout_schedule(&sc->callout, 1);
|
||||
|
||||
snd_mtxunlock(sc->lock);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -179,15 +197,15 @@ dummy_chan_trigger(kobj_t obj, void *data, int go)
|
||||
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
if (!callout_active(&sc->callout))
|
||||
callout_reset(&sc->callout, 1, dummy_chan_io, sc);
|
||||
ch->ptr = 0;
|
||||
ch->run = 1;
|
||||
callout_reset(&sc->callout, 1, dummy_chan_io, sc);
|
||||
break;
|
||||
case PCMTRIG_STOP:
|
||||
case PCMTRIG_ABORT:
|
||||
ch->run = 0;
|
||||
if (callout_active(&sc->callout))
|
||||
/* If all channels are stopped, stop the callout as well. */
|
||||
if (!dummy_active(sc))
|
||||
callout_stop(&sc->callout);
|
||||
default:
|
||||
break;
|
||||
@ -292,6 +310,7 @@ dummy_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_dummy softc");
|
||||
callout_init_mtx(&sc->callout, sc->lock, 0);
|
||||
|
||||
sc->cap_fmts[0] = SND_FORMAT(AFMT_S32_LE, 2, 0);
|
||||
sc->cap_fmts[1] = SND_FORMAT(AFMT_S24_LE, 2, 0);
|
||||
@ -316,7 +335,6 @@ dummy_attach(device_t dev)
|
||||
if (pcm_register(dev, status))
|
||||
return (ENXIO);
|
||||
mixer_init(dev, &dummy_mixer_class, sc);
|
||||
callout_init(&sc->callout, 1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -327,8 +345,8 @@ dummy_detach(device_t dev)
|
||||
struct dummy_softc *sc = device_get_softc(dev);
|
||||
int err;
|
||||
|
||||
callout_drain(&sc->callout);
|
||||
err = pcm_unregister(dev);
|
||||
callout_drain(&sc->callout);
|
||||
snd_mtxfree(sc->lock);
|
||||
|
||||
return (err);
|
||||
|
@ -309,14 +309,7 @@ chn_wakeup(struct pcm_channel *c)
|
||||
if (CHN_EMPTY(c, children.busy)) {
|
||||
if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
|
||||
selwakeuppri(sndbuf_getsel(bs), PRIBIO);
|
||||
if (c->flags & CHN_F_SLEEPING) {
|
||||
/*
|
||||
* Ok, I can just panic it right here since it is
|
||||
* quite obvious that we never allow multiple waiters
|
||||
* from userland. I'm too generous...
|
||||
*/
|
||||
CHN_BROADCAST(&c->intr_cv);
|
||||
}
|
||||
CHN_BROADCAST(&c->intr_cv);
|
||||
} else {
|
||||
CHN_FOREACH(ch, c, children.busy) {
|
||||
CHN_LOCK(ch);
|
||||
@ -332,15 +325,11 @@ chn_sleep(struct pcm_channel *c, int timeout)
|
||||
int ret;
|
||||
|
||||
CHN_LOCKASSERT(c);
|
||||
KASSERT((c->flags & CHN_F_SLEEPING) == 0,
|
||||
("%s(): entered with CHN_F_SLEEPING", __func__));
|
||||
|
||||
if (c->flags & CHN_F_DEAD)
|
||||
return (EINVAL);
|
||||
|
||||
c->flags |= CHN_F_SLEEPING;
|
||||
ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout);
|
||||
c->flags &= ~CHN_F_SLEEPING;
|
||||
|
||||
return ((c->flags & CHN_F_DEAD) ? EINVAL : ret);
|
||||
}
|
||||
@ -2318,44 +2307,46 @@ chn_trigger(struct pcm_channel *c, int go)
|
||||
if (go == c->trigger)
|
||||
return (0);
|
||||
|
||||
if (snd_verbose > 3) {
|
||||
device_printf(c->dev, "%s() %s: calling go=0x%08x , "
|
||||
"prev=0x%08x\n", __func__, c->name, go, c->trigger);
|
||||
}
|
||||
|
||||
c->trigger = go;
|
||||
ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
CHN_UNLOCK(c);
|
||||
PCM_LOCK(d);
|
||||
CHN_LOCK(c);
|
||||
|
||||
/*
|
||||
* Do nothing if another thread set a different trigger while we had
|
||||
* dropped the mutex.
|
||||
*/
|
||||
if (go != c->trigger) {
|
||||
PCM_UNLOCK(d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the SAFE variants to prevent inserting/removing an already
|
||||
* existing/missing element.
|
||||
*/
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
if (snd_verbose > 3)
|
||||
device_printf(c->dev,
|
||||
"%s() %s: calling go=0x%08x , "
|
||||
"prev=0x%08x\n", __func__, c->name, go,
|
||||
c->trigger);
|
||||
if (c->trigger != PCMTRIG_START) {
|
||||
c->trigger = go;
|
||||
CHN_UNLOCK(c);
|
||||
PCM_LOCK(d);
|
||||
CHN_INSERT_HEAD(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
CHN_LOCK(c);
|
||||
chn_syncstate(c);
|
||||
}
|
||||
CHN_INSERT_HEAD_SAFE(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
chn_syncstate(c);
|
||||
break;
|
||||
case PCMTRIG_STOP:
|
||||
case PCMTRIG_ABORT:
|
||||
if (snd_verbose > 3)
|
||||
device_printf(c->dev,
|
||||
"%s() %s: calling go=0x%08x , "
|
||||
"prev=0x%08x\n", __func__, c->name, go,
|
||||
c->trigger);
|
||||
if (c->trigger == PCMTRIG_START) {
|
||||
c->trigger = go;
|
||||
CHN_UNLOCK(c);
|
||||
PCM_LOCK(d);
|
||||
CHN_REMOVE(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
CHN_LOCK(c);
|
||||
}
|
||||
CHN_REMOVE_SAFE(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
break;
|
||||
default:
|
||||
PCM_UNLOCK(d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ enum {
|
||||
#define CHN_F_RUNNING 0x00000004 /* dma is running */
|
||||
#define CHN_F_TRIGGERED 0x00000008
|
||||
#define CHN_F_NOTRIGGER 0x00000010
|
||||
#define CHN_F_SLEEPING 0x00000020
|
||||
/* unused 0x00000020 */
|
||||
|
||||
#define CHN_F_NBIO 0x00000040 /* do non-blocking i/o */
|
||||
#define CHN_F_MMAP 0x00000080 /* has been mmap()ed */
|
||||
@ -362,7 +362,7 @@ enum {
|
||||
#define CHN_F_BUSY 0x00000100 /* has been opened */
|
||||
#define CHN_F_DIRTY 0x00000200 /* need re-config */
|
||||
#define CHN_F_DEAD 0x00000400 /* too many errors, dead, mdk */
|
||||
#define CHN_F_SILENCE 0x00000800 /* silence, nil, null, yada */
|
||||
/* unused 0x00000800 */
|
||||
|
||||
#define CHN_F_HAS_SIZE 0x00001000 /* user set block size */
|
||||
#define CHN_F_HAS_VCHAN 0x00002000 /* vchan master */
|
||||
@ -381,14 +381,14 @@ enum {
|
||||
"\002ABORTING" \
|
||||
"\003RUNNING" \
|
||||
"\004TRIGGERED" \
|
||||
/* \006 */ \
|
||||
"\005NOTRIGGER" \
|
||||
"\006SLEEPING" \
|
||||
"\007NBIO" \
|
||||
"\010MMAP" \
|
||||
"\011BUSY" \
|
||||
"\012DIRTY" \
|
||||
"\013DEAD" \
|
||||
"\014SILENCE" \
|
||||
/* \014 */ \
|
||||
"\015HAS_SIZE" \
|
||||
"\016HAS_VCHAN" \
|
||||
"\017VCHAN_PASSTHROUGH" \
|
||||
|
@ -137,7 +137,7 @@ dsp_destroy_dev(device_t dev)
|
||||
struct snddev_info *d;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
destroy_dev_sched(d->dsp_dev);
|
||||
destroy_dev(d->dsp_dev);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -177,7 +177,7 @@ dsp_close(void *data)
|
||||
|
||||
d = priv->sc;
|
||||
/* At this point pcm_unregister() will destroy all channels anyway. */
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
goto skip;
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -264,7 +264,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
||||
return (ENODEV);
|
||||
|
||||
d = i_dev->si_drv1;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
@ -445,7 +445,7 @@ dsp_io_ops(struct dsp_cdevpriv *priv, struct uio *buf)
|
||||
("%s(): io train wreck!", __func__));
|
||||
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -664,7 +664,7 @@ dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
|
||||
return (err);
|
||||
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -1783,7 +1783,7 @@ dsp_poll(struct cdev *i_dev, int events, struct thread *td)
|
||||
if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
|
||||
return (err);
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d)) {
|
||||
if (!DSP_REGISTERED(d)) {
|
||||
/* XXX many clients don't understand POLLNVAL */
|
||||
return (events & (POLLHUP | POLLPRI | POLLIN |
|
||||
POLLRDNORM | POLLOUT | POLLWRNORM));
|
||||
@ -1865,7 +1865,7 @@ dsp_mmap_single(struct cdev *i_dev, vm_ooffset_t *offset,
|
||||
if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
|
||||
return (err);
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EINVAL);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
|
@ -146,7 +146,7 @@ mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
|
||||
struct pcm_channel *c;
|
||||
int dropmtx, acquiremtx;
|
||||
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EINVAL);
|
||||
|
||||
if (mtx_owned(m->lock))
|
||||
@ -199,7 +199,7 @@ mixer_set_eq(struct snd_mixer *m, struct snddev_info *d,
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EINVAL);
|
||||
|
||||
if (mtx_owned(m->lock))
|
||||
@ -1053,7 +1053,7 @@ mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
||||
|
||||
m = i_dev->si_drv1;
|
||||
d = device_get_softc(m->dev);
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
/* XXX Need Giant magic entry ??? */
|
||||
@ -1209,7 +1209,7 @@ mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
|
||||
return (EBADF);
|
||||
|
||||
d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -1447,7 +1447,7 @@ mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
|
||||
for (i = 0; pcm_devclass != NULL &&
|
||||
i < devclass_get_maxunit(pcm_devclass); i++) {
|
||||
d = devclass_get_softc(pcm_devclass, i);
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d)) {
|
||||
if (!PCM_REGISTERED(d)) {
|
||||
if ((mi->dev == -1 && i == snd_unit) || mi->dev == i) {
|
||||
mixer_oss_mixerinfo_unavail(mi, i);
|
||||
return (0);
|
||||
|
@ -211,40 +211,53 @@ static void
|
||||
pcm_killchans(struct snddev_info *d)
|
||||
{
|
||||
struct pcm_channel *ch;
|
||||
bool found;
|
||||
bool again;
|
||||
|
||||
PCM_BUSYASSERT(d);
|
||||
do {
|
||||
found = false;
|
||||
KASSERT(!PCM_REGISTERED(d), ("%s(): still registered\n", __func__));
|
||||
|
||||
for (;;) {
|
||||
again = false;
|
||||
/* Make sure all channels are stopped. */
|
||||
CHN_FOREACH(ch, d, channels.pcm) {
|
||||
CHN_LOCK(ch);
|
||||
/*
|
||||
* Make sure no channel has went to sleep in the
|
||||
* meantime.
|
||||
*/
|
||||
chn_shutdown(ch);
|
||||
/*
|
||||
* We have to give a thread sleeping in chn_sleep() a
|
||||
* chance to observe that the channel is dead.
|
||||
*/
|
||||
if ((ch->flags & CHN_F_SLEEPING) == 0) {
|
||||
found = true;
|
||||
if (ch->intr_cv.cv_waiters == 0 && CHN_STOPPED(ch) &&
|
||||
ch->inprog == 0) {
|
||||
CHN_UNLOCK(ch);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
chn_shutdown(ch);
|
||||
if (ch->direction == PCMDIR_PLAY)
|
||||
chn_flush(ch);
|
||||
else
|
||||
chn_abort(ch);
|
||||
CHN_UNLOCK(ch);
|
||||
again = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* All channels are still sleeping. Sleep for a bit and try
|
||||
* again to see if any of them is awake now.
|
||||
* Some channels are still active. Sleep for a bit and try
|
||||
* again.
|
||||
*/
|
||||
if (!found) {
|
||||
pause_sbt("pcmkillchans", SBT_1MS * 5, 0, 0);
|
||||
continue;
|
||||
}
|
||||
if (again)
|
||||
pause_sbt("pcmkillchans", mstosbt(5), 0, 0);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* All channels are finally dead. */
|
||||
while (!CHN_EMPTY(d, channels.pcm)) {
|
||||
ch = CHN_FIRST(d, channels.pcm);
|
||||
chn_kill(ch);
|
||||
} while (!CHN_EMPTY(d, channels.pcm));
|
||||
}
|
||||
|
||||
if (d->p_unr != NULL)
|
||||
delete_unrhdr(d->p_unr);
|
||||
if (d->vp_unr != NULL)
|
||||
delete_unrhdr(d->vp_unr);
|
||||
if (d->r_unr != NULL)
|
||||
delete_unrhdr(d->r_unr);
|
||||
if (d->vr_unr != NULL)
|
||||
delete_unrhdr(d->vr_unr);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -512,7 +525,6 @@ int
|
||||
pcm_unregister(device_t dev)
|
||||
{
|
||||
struct snddev_info *d;
|
||||
struct pcm_channel *ch;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
|
||||
@ -524,29 +536,14 @@ pcm_unregister(device_t dev)
|
||||
PCM_LOCK(d);
|
||||
PCM_WAIT(d);
|
||||
|
||||
d->flags |= SD_F_DETACHING;
|
||||
d->flags &= ~SD_F_REGISTERED;
|
||||
|
||||
PCM_ACQUIRE(d);
|
||||
PCM_UNLOCK(d);
|
||||
|
||||
CHN_FOREACH(ch, d, channels.pcm) {
|
||||
CHN_LOCK(ch);
|
||||
/*
|
||||
* Do not wait for the timeout in chn_read()/chn_write(). Wake
|
||||
* up the sleeping thread and kill the channel.
|
||||
*/
|
||||
chn_shutdown(ch);
|
||||
chn_abort(ch);
|
||||
CHN_UNLOCK(ch);
|
||||
}
|
||||
pcm_killchans(d);
|
||||
|
||||
/* remove /dev/sndstat entry first */
|
||||
sndstat_unregister(dev);
|
||||
|
||||
PCM_LOCK(d);
|
||||
d->flags |= SD_F_DYING;
|
||||
d->flags &= ~SD_F_REGISTERED;
|
||||
PCM_UNLOCK(d);
|
||||
PCM_RELEASE_QUICK(d);
|
||||
|
||||
if (d->play_sysctl_tree != NULL) {
|
||||
sysctl_ctx_free(&d->play_sysctl_ctx);
|
||||
@ -557,24 +554,12 @@ pcm_unregister(device_t dev)
|
||||
d->rec_sysctl_tree = NULL;
|
||||
}
|
||||
|
||||
sndstat_unregister(dev);
|
||||
mixer_uninit(dev);
|
||||
dsp_destroy_dev(dev);
|
||||
(void)mixer_uninit(dev);
|
||||
|
||||
pcm_killchans(d);
|
||||
|
||||
PCM_LOCK(d);
|
||||
PCM_RELEASE(d);
|
||||
cv_destroy(&d->cv);
|
||||
PCM_UNLOCK(d);
|
||||
snd_mtxfree(d->lock);
|
||||
if (d->p_unr != NULL)
|
||||
delete_unrhdr(d->p_unr);
|
||||
if (d->vp_unr != NULL)
|
||||
delete_unrhdr(d->vp_unr);
|
||||
if (d->r_unr != NULL)
|
||||
delete_unrhdr(d->r_unr);
|
||||
if (d->vr_unr != NULL)
|
||||
delete_unrhdr(d->vr_unr);
|
||||
|
||||
if (snd_unit == device_get_unit(dev)) {
|
||||
snd_unit = pcm_best_unit(-1);
|
||||
|
@ -104,17 +104,15 @@ struct snd_mixer;
|
||||
#define SD_F_SIMPLEX 0x00000001
|
||||
#define SD_F_AUTOVCHAN 0x00000002
|
||||
#define SD_F_SOFTPCMVOL 0x00000004
|
||||
#define SD_F_DYING 0x00000008
|
||||
#define SD_F_DETACHING 0x00000010
|
||||
#define SD_F_BUSY 0x00000020
|
||||
#define SD_F_MPSAFE 0x00000040
|
||||
#define SD_F_REGISTERED 0x00000080
|
||||
#define SD_F_BITPERFECT 0x00000100
|
||||
#define SD_F_VPC 0x00000200 /* volume-per-channel */
|
||||
#define SD_F_EQ 0x00000400 /* EQ */
|
||||
#define SD_F_EQ_ENABLED 0x00000800 /* EQ enabled */
|
||||
#define SD_F_EQ_BYPASSED 0x00001000 /* EQ bypassed */
|
||||
#define SD_F_EQ_PC 0x00002000 /* EQ per-channel */
|
||||
#define SD_F_BUSY 0x00000008
|
||||
#define SD_F_MPSAFE 0x00000010
|
||||
#define SD_F_REGISTERED 0x00000020
|
||||
#define SD_F_BITPERFECT 0x00000040
|
||||
#define SD_F_VPC 0x00000080 /* volume-per-channel */
|
||||
#define SD_F_EQ 0x00000100 /* EQ */
|
||||
#define SD_F_EQ_ENABLED 0x00000200 /* EQ enabled */
|
||||
#define SD_F_EQ_BYPASSED 0x00000400 /* EQ bypassed */
|
||||
#define SD_F_EQ_PC 0x00000800 /* EQ per-channel */
|
||||
|
||||
#define SD_F_EQ_DEFAULT (SD_F_EQ | SD_F_EQ_ENABLED)
|
||||
#define SD_F_EQ_MASK (SD_F_EQ | SD_F_EQ_ENABLED | \
|
||||
@ -127,26 +125,20 @@ struct snd_mixer;
|
||||
"\001SIMPLEX" \
|
||||
"\002AUTOVCHAN" \
|
||||
"\003SOFTPCMVOL" \
|
||||
"\004DYING" \
|
||||
"\005DETACHING" \
|
||||
"\006BUSY" \
|
||||
"\007MPSAFE" \
|
||||
"\010REGISTERED" \
|
||||
"\011BITPERFECT" \
|
||||
"\012VPC" \
|
||||
"\013EQ" \
|
||||
"\014EQ_ENABLED" \
|
||||
"\015EQ_BYPASSED" \
|
||||
"\016EQ_PC" \
|
||||
"\004BUSY" \
|
||||
"\005MPSAFE" \
|
||||
"\006REGISTERED" \
|
||||
"\007BITPERFECT" \
|
||||
"\010VPC" \
|
||||
"\011EQ" \
|
||||
"\012EQ_ENABLED" \
|
||||
"\013EQ_BYPASSED" \
|
||||
"\014EQ_PC" \
|
||||
"\035PRIO_RD" \
|
||||
"\036PRIO_WR"
|
||||
|
||||
#define PCM_ALIVE(x) ((x) != NULL && (x)->lock != NULL && \
|
||||
!((x)->flags & SD_F_DYING))
|
||||
#define PCM_REGISTERED(x) (PCM_ALIVE(x) && \
|
||||
((x)->flags & SD_F_REGISTERED))
|
||||
|
||||
#define PCM_DETACHING(x) ((x)->flags & SD_F_DETACHING)
|
||||
#define PCM_ALIVE(x) ((x) != NULL && (x)->lock != NULL)
|
||||
#define PCM_REGISTERED(x) (PCM_ALIVE(x) && ((x)->flags & SD_F_REGISTERED))
|
||||
|
||||
#define PCM_CHANCOUNT(d) \
|
||||
(d->playcount + d->pvchancount + d->reccount + d->rvchancount)
|
||||
|
@ -146,20 +146,19 @@ vchan_trigger(kobj_t obj, void *data, int go)
|
||||
int ret, otrigger;
|
||||
|
||||
info = data;
|
||||
c = info->channel;
|
||||
p = c->parentchannel;
|
||||
|
||||
CHN_LOCKASSERT(c);
|
||||
if (!PCMTRIG_COMMON(go) || go == info->trigger)
|
||||
return (0);
|
||||
|
||||
c = info->channel;
|
||||
p = c->parentchannel;
|
||||
otrigger = info->trigger;
|
||||
info->trigger = go;
|
||||
|
||||
CHN_LOCKASSERT(c);
|
||||
|
||||
CHN_UNLOCK(c);
|
||||
CHN_LOCK(p);
|
||||
|
||||
otrigger = info->trigger;
|
||||
info->trigger = go;
|
||||
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
if (otrigger != PCMTRIG_START)
|
||||
|
@ -365,6 +365,16 @@ sigqueue_start(void)
|
||||
SIGFILLSET(fastblock_mask);
|
||||
SIG_CANTMASK(fastblock_mask);
|
||||
ast_register(TDA_SIG, ASTR_UNCOND, 0, ast_sig);
|
||||
|
||||
/*
|
||||
* TDA_PSELECT is for the case where the signal mask should be restored
|
||||
* before delivering any signals so that we do not deliver any that are
|
||||
* blocked by the normal thread mask. It is mutually exclusive with
|
||||
* TDA_SIGSUSPEND, which should be used if we *do* want to deliver
|
||||
* signals that are normally blocked, e.g., if it interrupted our sleep.
|
||||
*/
|
||||
ast_register(TDA_PSELECT, ASTR_ASTF_REQUIRED | ASTR_TDP,
|
||||
TDP_OLDMASK, ast_sigsuspend);
|
||||
ast_register(TDA_SIGSUSPEND, ASTR_ASTF_REQUIRED | ASTR_TDP,
|
||||
TDP_OLDMASK, ast_sigsuspend);
|
||||
}
|
||||
|
@ -1049,14 +1049,26 @@ kern_pselect(struct thread *td, int nd, fd_set *in, fd_set *ou, fd_set *ex,
|
||||
if (error != 0)
|
||||
return (error);
|
||||
td->td_pflags |= TDP_OLDMASK;
|
||||
}
|
||||
error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits);
|
||||
if (uset != NULL) {
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
* usermode and TDP_OLDMASK is cleared, restoring old
|
||||
* sigmask.
|
||||
* sigmask. If we didn't get interrupted, then the caller is
|
||||
* likely not expecting a signal to hit that should normally be
|
||||
* blocked by its signal mask, so we restore the mask before
|
||||
* any signals could be delivered.
|
||||
*/
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
if (error == EINTR) {
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
} else {
|
||||
/* *select(2) should never restart. */
|
||||
MPASS(error != ERESTART);
|
||||
ast_sched(td, TDA_PSELECT);
|
||||
}
|
||||
}
|
||||
error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1528,12 +1540,6 @@ kern_poll_kfds(struct thread *td, struct pollfd *kfds, u_int nfds,
|
||||
if (error)
|
||||
return (error);
|
||||
td->td_pflags |= TDP_OLDMASK;
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
* usermode and TDP_OLDMASK is cleared, restoring old
|
||||
* sigmask.
|
||||
*/
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
}
|
||||
|
||||
seltdinit(td);
|
||||
@ -1556,6 +1562,22 @@ kern_poll_kfds(struct thread *td, struct pollfd *kfds, u_int nfds,
|
||||
error = EINTR;
|
||||
if (error == EWOULDBLOCK)
|
||||
error = 0;
|
||||
|
||||
if (uset != NULL) {
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
* usermode and TDP_OLDMASK is cleared, restoring old
|
||||
* sigmask. If we didn't get interrupted, then the caller is
|
||||
* likely not expecting a signal to hit that should normally be
|
||||
* blocked by its signal mask, so we restore the mask before
|
||||
* any signals could be delivered.
|
||||
*/
|
||||
if (error == EINTR)
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
else
|
||||
ast_sched(td, TDA_PSELECT);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,8 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define PF_PFIL_NOREFRAGMENT 0x80000000
|
||||
|
||||
#if defined(__arm__)
|
||||
#define PF_WANT_32_TO_64_COUNTER
|
||||
#endif
|
||||
@ -2372,7 +2374,8 @@ void pf_poolmask(struct pf_addr *, struct pf_addr*,
|
||||
struct pf_addr *, struct pf_addr *, sa_family_t);
|
||||
void pf_addr_inc(struct pf_addr *, sa_family_t);
|
||||
int pf_max_frag_size(struct mbuf *);
|
||||
int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *, bool);
|
||||
int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *,
|
||||
struct ifnet *, bool);
|
||||
#endif /* INET6 */
|
||||
|
||||
int pf_multihome_scan_init(int, int, struct pf_pdesc *);
|
||||
|
@ -7927,6 +7927,7 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
struct pf_kstate *s, struct pf_pdesc *pd, struct inpcb *inp)
|
||||
{
|
||||
struct mbuf *m0, *md;
|
||||
struct m_tag *mtag;
|
||||
struct sockaddr_in6 dst;
|
||||
struct ip6_hdr *ip6;
|
||||
struct pfi_kkif *nkif = NULL;
|
||||
@ -8053,8 +8054,8 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
}
|
||||
|
||||
if (pd->dir == PF_IN) {
|
||||
if (pf_test(AF_INET6, PF_OUT, PFIL_FWD, ifp, &m0, inp,
|
||||
&pd->act) != PF_PASS) {
|
||||
if (pf_test(AF_INET6, PF_OUT, PFIL_FWD | PF_PFIL_NOREFRAGMENT,
|
||||
ifp, &m0, inp, &pd->act) != PF_PASS) {
|
||||
SDT_PROBE1(pf, ip6, route_to, drop, __LINE__);
|
||||
goto bad;
|
||||
} else if (m0 == NULL) {
|
||||
@ -8087,6 +8088,14 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
*/
|
||||
if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr))
|
||||
dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL);
|
||||
if (mtag != NULL) {
|
||||
int ret;
|
||||
ret = pf_refragment6(ifp, &m0, mtag, ifp, true);
|
||||
SDT_PROBE2(pf, ip6, route_to, output, ifp, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
|
||||
md = m0;
|
||||
pf_dummynet_route(pd, s, r, ifp, sintosa(&dst), &md);
|
||||
@ -9474,14 +9483,15 @@ eat_pkt:
|
||||
if (s)
|
||||
PF_STATE_UNLOCK(s);
|
||||
|
||||
out:
|
||||
#ifdef INET6
|
||||
/* If reassembled packet passed, create new fragments. */
|
||||
if (af == AF_INET6 && action == PF_PASS && *m0 && dir == PF_OUT &&
|
||||
(! (pflags & PF_PFIL_NOREFRAGMENT)) &&
|
||||
(mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL)) != NULL)
|
||||
action = pf_refragment6(ifp, m0, mtag, pflags & PFIL_FWD);
|
||||
action = pf_refragment6(ifp, m0, mtag, NULL, pflags & PFIL_FWD);
|
||||
#endif
|
||||
|
||||
out:
|
||||
pf_sctp_multihome_delayed(&pd, kif, s, action);
|
||||
|
||||
return (action);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/vnet.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pflog.h>
|
||||
@ -49,6 +50,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
#include <netinet/tcp.h>
|
||||
@ -958,7 +961,7 @@ pf_max_frag_size(struct mbuf *m)
|
||||
|
||||
int
|
||||
pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
|
||||
bool forward)
|
||||
struct ifnet *rt, bool forward)
|
||||
{
|
||||
struct mbuf *m = *m0, *t;
|
||||
struct ip6_hdr *hdr;
|
||||
@ -1029,16 +1032,27 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
|
||||
m->m_flags |= M_SKIP_FIREWALL;
|
||||
memset(&pd, 0, sizeof(pd));
|
||||
pd.pf_mtag = pf_find_mtag(m);
|
||||
if (error == 0)
|
||||
if (forward) {
|
||||
MPASS(m->m_pkthdr.rcvif != NULL);
|
||||
ip6_forward(m, 0);
|
||||
} else {
|
||||
(void)ip6_output(m, NULL, NULL, 0, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
if (error != 0) {
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
if (rt != NULL) {
|
||||
struct sockaddr_in6 dst;
|
||||
hdr = mtod(m, struct ip6_hdr *);
|
||||
|
||||
bzero(&dst, sizeof(dst));
|
||||
dst.sin6_family = AF_INET6;
|
||||
dst.sin6_len = sizeof(dst);
|
||||
dst.sin6_addr = hdr->ip6_dst;
|
||||
|
||||
nd6_output_ifp(rt, rt, m, &dst, NULL);
|
||||
} else if (forward) {
|
||||
MPASS(m->m_pkthdr.rcvif != NULL);
|
||||
ip6_forward(m, 0);
|
||||
} else {
|
||||
(void)ip6_output(m, NULL, NULL, 0, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (action);
|
||||
|
@ -73,7 +73,7 @@
|
||||
* cannot include sys/param.h and should only be updated here.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1500027
|
||||
#define __FreeBSD_version 1500028
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
@ -494,6 +494,7 @@ enum {
|
||||
TDA_RACCT,
|
||||
TDA_MOD1, /* For third party use, before signals are */
|
||||
TAD_MOD2, /* processed .. */
|
||||
TDA_PSELECT, /* For discarding temporary signal mask */
|
||||
TDA_SIG,
|
||||
TDA_KTRACE,
|
||||
TDA_SUSPEND,
|
||||
|
@ -277,7 +277,7 @@ amdiommu_create_dev_tbl(struct amdiommu_unit *sc)
|
||||
pmap_qenter(seg_vaddr, &m, 1);
|
||||
}
|
||||
reg = i == 0 ? AMDIOMMU_DEVTAB_BASE : AMDIOMMU_DEVTAB_S1_BASE +
|
||||
i - 1;
|
||||
((i - 1) << 3);
|
||||
amdiommu_write8(sc, reg, rval);
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,75 @@ v6_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "v6_route_to" "cleanup"
|
||||
v6_route_to_head()
|
||||
{
|
||||
atf_set descr 'Test IPv6 reassembly combined with route-to'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
v6_route_to_body()
|
||||
{
|
||||
pft_init
|
||||
}
|
||||
|
||||
v6_route_to_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
|
||||
epair_send=$(vnet_mkepair)
|
||||
epair_link=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail alcatraz ${epair_send}b ${epair_link}a
|
||||
vnet_mkjail singsing ${epair_link}b
|
||||
|
||||
ifconfig ${epair_send}a inet6 2001:db8:42::1/64 no_dad up
|
||||
|
||||
jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 no_dad up
|
||||
jexec alcatraz ifconfig ${epair_link}a inet6 2001:db8:43::2/64 no_dad up
|
||||
jexec alcatraz sysctl net.inet6.ip6.forwarding=1
|
||||
|
||||
jexec singsing ifconfig ${epair_link}b inet6 2001:db8:43::3/64 no_dad up
|
||||
jexec singsing route add -6 2001:db8:42::/64 2001:db8:43::2
|
||||
route add -6 2001:db8:43::/64 2001:db8:42::2
|
||||
|
||||
jexec alcatraz ifconfig ${epair_send}b inet6 -ifdisabled
|
||||
jexec alcatraz ifconfig ${epair_link}a inet6 -ifdisabled
|
||||
jexec singsing ifconfig ${epair_link}b inet6 -ifdisabled
|
||||
ifconfig ${epair_send}a inet6 -ifdisabled
|
||||
|
||||
jexec alcatraz pfctl -e
|
||||
pft_set_rules alcatraz \
|
||||
"set reassemble yes" \
|
||||
"pass" \
|
||||
"pass in route-to (${epair_link}a 2001:db8:43::3) inet6 proto icmp6 from any to 2001:db8:43::3 keep state"
|
||||
|
||||
# Forwarding test
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 -s 4500 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore\
|
||||
ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3
|
||||
|
||||
# Now test this without fragmentation
|
||||
pft_set_rules alcatraz \
|
||||
"set reassemble no" \
|
||||
"pass" \
|
||||
"pass in route-to (${epair_link}a 2001:db8:43::3) inet6 proto icmp6 from any to 2001:db8:43::3 keep state"
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 -s 4500 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore\
|
||||
ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3
|
||||
}
|
||||
|
||||
atf_test_case "mtu_diff" "cleanup"
|
||||
mtu_diff_head()
|
||||
{
|
||||
@ -544,6 +613,7 @@ atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "too_many_fragments"
|
||||
atf_add_test_case "v6"
|
||||
atf_add_test_case "v6_route_to"
|
||||
atf_add_test_case "mtu_diff"
|
||||
atf_add_test_case "overreplace"
|
||||
atf_add_test_case "overindex"
|
||||
|
@ -578,7 +578,7 @@ netname4(in_addr_t in, in_addr_t mask)
|
||||
struct netent *np = 0;
|
||||
in_addr_t i;
|
||||
|
||||
if (in == INADDR_ANY && mask == 0) {
|
||||
if (!numeric_addr && in == INADDR_ANY && mask == 0) {
|
||||
strlcpy(line, "default", sizeof(line));
|
||||
return (line);
|
||||
}
|
||||
@ -673,7 +673,8 @@ netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask)
|
||||
else
|
||||
masklen = 128;
|
||||
|
||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||
if (!numeric_addr && masklen == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||
return("default");
|
||||
|
||||
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, nline, sizeof(nline),
|
||||
|
Loading…
Reference in New Issue
Block a user