MFhead @ r275663
This commit is contained in:
commit
f0d7e7f714
@ -793,6 +793,11 @@ ITOOLS= [ awk cap_mkdb cat chflags chmod chown \
|
||||
rm sed services_mkdb sh sysctl test true uname wc ${_zoneinfo} \
|
||||
${LOCAL_ITOOLS}
|
||||
|
||||
# Needed for share/man
|
||||
.if ${MK_MAN} != "no"
|
||||
ITOOLS+=makewhatis
|
||||
.endif
|
||||
|
||||
#
|
||||
# distributeworld
|
||||
#
|
||||
|
@ -5,8 +5,7 @@ MAN = freebsd-version.1
|
||||
CLEANFILES = freebsd-version.sh
|
||||
NEWVERS = ${.CURDIR}/../../sys/conf/newvers.sh
|
||||
|
||||
freebsd-version.sh.in: ${NEWVERS}
|
||||
freebsd-version.sh: ${.CURDIR}/freebsd-version.sh.in
|
||||
freebsd-version.sh: ${.CURDIR}/freebsd-version.sh.in ${NEWVERS}
|
||||
eval $$(egrep '^(TYPE|REVISION|BRANCH)=' ${NEWVERS}) ; \
|
||||
if ! sed -e "\
|
||||
s/@@TYPE@@/$${TYPE}/g; \
|
||||
|
@ -233,12 +233,11 @@ tpool_create(uint_t min_threads, uint_t max_threads, uint_t linger,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
tpool = malloc(sizeof (*tpool));
|
||||
tpool = calloc(1, sizeof (*tpool));
|
||||
if (tpool == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
bzero(tpool, sizeof(*tpool));
|
||||
(void) pthread_mutex_init(&tpool->tp_mutex, NULL);
|
||||
(void) pthread_cond_init(&tpool->tp_busycv, NULL);
|
||||
(void) pthread_cond_init(&tpool->tp_workcv, NULL);
|
||||
@ -267,9 +266,8 @@ tpool_dispatch(tpool_t *tpool, void (*func)(void *), void *arg)
|
||||
{
|
||||
tpool_job_t *job;
|
||||
|
||||
if ((job = malloc(sizeof (*job))) == NULL)
|
||||
if ((job = calloc(1, sizeof (*job))) == NULL)
|
||||
return (-1);
|
||||
bzero(job, sizeof(*job));
|
||||
job->tpj_next = NULL;
|
||||
job->tpj_func = func;
|
||||
job->tpj_arg = arg;
|
||||
|
1140
cddl/contrib/opensolaris/lib/libctf/common/ctf.5
Normal file
1140
cddl/contrib/opensolaris/lib/libctf/common/ctf.5
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@ SRCS= ctf_create.c \
|
||||
ctf_subr.c \
|
||||
ctf_types.c \
|
||||
ctf_util.c
|
||||
MAN= ctf.5
|
||||
|
||||
WARNS?= 0
|
||||
CFLAGS+= -DCTF_OLD_VERSIONS
|
||||
|
@ -2864,6 +2864,14 @@ bool LoopVectorizationLegality::canVectorize() {
|
||||
if (!TheLoop->getExitingBlock())
|
||||
return false;
|
||||
|
||||
// We only handle bottom-tested loops, i.e. loop in which the condition is
|
||||
// checked at the end of each iteration. With that we can assume that all
|
||||
// instructions in the loop are executed the same number of times.
|
||||
if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) {
|
||||
DEBUG(dbgs() << "LV: loop control flow is not understood by vectorizer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need to have a loop header.
|
||||
DEBUG(dbgs() << "LV: Found a loop: " <<
|
||||
TheLoop->getHeader()->getName() << '\n');
|
||||
|
@ -0,0 +1,71 @@
|
||||
Pull in r223171 from upstream llvm trunk (by Michael Zolotukhin):
|
||||
|
||||
PR21302. Vectorize only bottom-tested loops.
|
||||
|
||||
rdar://problem/18886083
|
||||
|
||||
This fixes a bug in the llvm vectorizer, which could sometimes cause
|
||||
vectorized loops to perform an additional iteration, leading to possible
|
||||
buffer overruns. Symptoms of this, which are usually segfaults, were
|
||||
first noticed when building gcc ports, here:
|
||||
|
||||
https://lists.freebsd.org/pipermail/freebsd-ports/2014-September/095466.html
|
||||
https://lists.freebsd.org/pipermail/freebsd-toolchain/2014-September/001211.html
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/275633
|
||||
|
||||
Index: lib/Transforms/Vectorize/LoopVectorize.cpp
|
||||
===================================================================
|
||||
--- lib/Transforms/Vectorize/LoopVectorize.cpp (revision 21)
|
||||
+++ lib/Transforms/Vectorize/LoopVectorize.cpp (revision 22)
|
||||
@@ -2864,6 +2864,14 @@ bool LoopVectorizationLegality::canVectorize() {
|
||||
if (!TheLoop->getExitingBlock())
|
||||
return false;
|
||||
|
||||
+ // We only handle bottom-tested loops, i.e. loop in which the condition is
|
||||
+ // checked at the end of each iteration. With that we can assume that all
|
||||
+ // instructions in the loop are executed the same number of times.
|
||||
+ if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) {
|
||||
+ DEBUG(dbgs() << "LV: loop control flow is not understood by vectorizer\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
// We need to have a loop header.
|
||||
DEBUG(dbgs() << "LV: Found a loop: " <<
|
||||
TheLoop->getHeader()->getName() << '\n');
|
||||
Index: test/Transforms/LoopVectorize/loop-form.ll
|
||||
===================================================================
|
||||
--- test/Transforms/LoopVectorize/loop-form.ll (revision 0)
|
||||
+++ test/Transforms/LoopVectorize/loop-form.ll (revision 22)
|
||||
@@ -0,0 +1,31 @@
|
||||
+; RUN: opt -S -loop-vectorize < %s | FileCheck %s
|
||||
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
+
|
||||
+; Check that we vectorize only bottom-tested loops.
|
||||
+; This is a reduced testcase from PR21302.
|
||||
+;
|
||||
+; rdar://problem/18886083
|
||||
+
|
||||
+%struct.X = type { i32, i16 }
|
||||
+; CHECK-LABEL: @foo(
|
||||
+; CHECK-NOT: vector.body
|
||||
+
|
||||
+define void @foo(i32 %n) {
|
||||
+entry:
|
||||
+ br label %for.cond
|
||||
+
|
||||
+for.cond:
|
||||
+ %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
||||
+ %cmp = icmp slt i32 %i, %n
|
||||
+ br i1 %cmp, label %for.body, label %if.end
|
||||
+
|
||||
+for.body:
|
||||
+ %iprom = sext i32 %i to i64
|
||||
+ %b = getelementptr inbounds %struct.X* undef, i64 %iprom, i32 1
|
||||
+ store i16 0, i16* %b, align 4
|
||||
+ %inc = add nsw i32 %i, 1
|
||||
+ br label %for.cond
|
||||
+
|
||||
+if.end:
|
||||
+ ret void
|
||||
+}
|
@ -96,7 +96,7 @@ kgdb_thr_add_procs(uintptr_t paddr)
|
||||
kt->kaddr = addr;
|
||||
if (td.td_tid == dumptid)
|
||||
kt->pcb = dumppcb;
|
||||
else if (td.td_state == TDS_RUNNING &&
|
||||
else if (td.td_oncpu != NOCPU &&
|
||||
CPU_ISSET(td.td_oncpu, &stopped_cpus))
|
||||
kt->pcb = kgdb_trgt_core_pcb(td.td_oncpu);
|
||||
else
|
||||
|
@ -69,7 +69,7 @@ __ieee754_j0f(float x)
|
||||
}
|
||||
return z;
|
||||
}
|
||||
if(ix<0x3c000000) { /* |x| < 2**-7 */
|
||||
if(ix<0x3b000000) { /* |x| < 2**-9 */
|
||||
if(huge+x>one) { /* raise inexact if x != 0 */
|
||||
if(ix<0x39800000) return one; /* |x|<2**-12 */
|
||||
else return one - x*x/4;
|
||||
|
@ -125,7 +125,7 @@ main() {
|
||||
# All tests passed. Let's see what can possibly go wrong
|
||||
# from here. The search string specified should match this
|
||||
# in PCRE speak: ':[\t ]*'
|
||||
${svn} log ${rev} --search 'Relnotes:?[^ ]*' ${1} > ${where}
|
||||
${svn} log ${rev} --search 'Relnotes:*[A-Za-z0-9]*' ${1} > ${where}
|
||||
return $?
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,8 @@ Gigaset USB Adapter 54
|
||||
.It
|
||||
Inventel UR045G
|
||||
.It
|
||||
Netgear WG111v1 (rev2)
|
||||
.It
|
||||
SMC EZ ConnectG SMC2862W-G
|
||||
.It
|
||||
Sagem XG703A
|
||||
|
@ -26,5 +26,6 @@ dev/mmc/host/dwmmc.c optional dwmmc
|
||||
# BERI specific
|
||||
dev/beri/beri_ring.c optional beri_ring
|
||||
dev/beri/beri_mem.c optional beri_mem
|
||||
dev/beri/virtio/virtio.c optional beri_vtblk
|
||||
dev/beri/virtio/virtio.c optional beri_vtblk | vtbe
|
||||
dev/beri/virtio/virtio_block.c optional beri_vtblk
|
||||
dev/beri/virtio/network/if_vtbe.c optional vtbe
|
||||
|
@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
|
@ -142,14 +142,13 @@ bcmwd_watchdog_fn(void *private, u_int cmd, int *error)
|
||||
|
||||
if (cmd > 0) {
|
||||
sec = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000000;
|
||||
ticks = (sec << 16) & BCM2835_WDOG_TIME_MASK;
|
||||
if (ticks == 0) {
|
||||
if (sec == 0 || sec > 15) {
|
||||
/*
|
||||
* Can't arm
|
||||
* disable watchdog as watchdog(9) requires
|
||||
*/
|
||||
device_printf(sc->dev,
|
||||
"Can't arm, timeout is less than 1 second\n");
|
||||
"Can't arm, timeout must be between 1-15 seconds\n");
|
||||
WRITE(sc, BCM2835_RSTC_REG,
|
||||
(BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) |
|
||||
BCM2835_RSTC_RESET);
|
||||
@ -157,6 +156,7 @@ bcmwd_watchdog_fn(void *private, u_int cmd, int *error)
|
||||
return;
|
||||
}
|
||||
|
||||
ticks = (sec << 16) & BCM2835_WDOG_TIME_MASK;
|
||||
reg = (BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) | ticks;
|
||||
WRITE(sc, BCM2835_WDOG_REG, reg);
|
||||
|
||||
|
@ -123,6 +123,7 @@ device spibus
|
||||
device beri_ring
|
||||
device beri_mem
|
||||
device beri_vtblk
|
||||
device vtbe
|
||||
device altera_pio
|
||||
|
||||
# Ethernet
|
||||
|
@ -39,7 +39,8 @@
|
||||
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
|
||||
|
||||
memreserve = < 0x00000000 0x1000 >, /* SMP trampoline */
|
||||
< 0x00001000 0x1000 >; /* virtio block */
|
||||
< 0x00001000 0x1000 >, /* virtio block */
|
||||
< 0x00002000 0x1000 >; /* virtio net */
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
@ -111,6 +112,15 @@
|
||||
pio-recv = <&pio0>;
|
||||
pio-send = <&pio1>;
|
||||
beri-mem = <&beri_mem0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
beri_vtnet: vtnet@00002000 {
|
||||
compatible = "sri-cambridge,beri-vtnet";
|
||||
reg = <0x00002000 0x1000>;
|
||||
pio-recv = <&pio0>;
|
||||
pio-send = <&pio1>;
|
||||
beri-mem = <&beri_mem0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -1297,28 +1297,36 @@ metaslab_unload(metaslab_t *msp)
|
||||
msp->ms_weight &= ~METASLAB_ACTIVE_MASK;
|
||||
}
|
||||
|
||||
metaslab_t *
|
||||
metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg)
|
||||
int
|
||||
metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg,
|
||||
metaslab_t **msp)
|
||||
{
|
||||
vdev_t *vd = mg->mg_vd;
|
||||
objset_t *mos = vd->vdev_spa->spa_meta_objset;
|
||||
metaslab_t *msp;
|
||||
metaslab_t *ms;
|
||||
int error;
|
||||
|
||||
msp = kmem_zalloc(sizeof (metaslab_t), KM_SLEEP);
|
||||
mutex_init(&msp->ms_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
cv_init(&msp->ms_load_cv, NULL, CV_DEFAULT, NULL);
|
||||
msp->ms_id = id;
|
||||
msp->ms_start = id << vd->vdev_ms_shift;
|
||||
msp->ms_size = 1ULL << vd->vdev_ms_shift;
|
||||
ms = kmem_zalloc(sizeof (metaslab_t), KM_SLEEP);
|
||||
mutex_init(&ms->ms_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
cv_init(&ms->ms_load_cv, NULL, CV_DEFAULT, NULL);
|
||||
ms->ms_id = id;
|
||||
ms->ms_start = id << vd->vdev_ms_shift;
|
||||
ms->ms_size = 1ULL << vd->vdev_ms_shift;
|
||||
|
||||
/*
|
||||
* We only open space map objects that already exist. All others
|
||||
* will be opened when we finally allocate an object for it.
|
||||
*/
|
||||
if (object != 0) {
|
||||
VERIFY0(space_map_open(&msp->ms_sm, mos, object, msp->ms_start,
|
||||
msp->ms_size, vd->vdev_ashift, &msp->ms_lock));
|
||||
ASSERT(msp->ms_sm != NULL);
|
||||
error = space_map_open(&ms->ms_sm, mos, object, ms->ms_start,
|
||||
ms->ms_size, vd->vdev_ashift, &ms->ms_lock);
|
||||
|
||||
if (error != 0) {
|
||||
kmem_free(ms, sizeof (metaslab_t));
|
||||
return (error);
|
||||
}
|
||||
|
||||
ASSERT(ms->ms_sm != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1328,11 +1336,11 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg)
|
||||
* addition of new space; and for debugging, it ensures that we'd
|
||||
* data fault on any attempt to use this metaslab before it's ready.
|
||||
*/
|
||||
msp->ms_tree = range_tree_create(&metaslab_rt_ops, msp, &msp->ms_lock);
|
||||
metaslab_group_add(mg, msp);
|
||||
ms->ms_tree = range_tree_create(&metaslab_rt_ops, ms, &ms->ms_lock);
|
||||
metaslab_group_add(mg, ms);
|
||||
|
||||
msp->ms_fragmentation = metaslab_fragmentation(msp);
|
||||
msp->ms_ops = mg->mg_class->mc_ops;
|
||||
ms->ms_fragmentation = metaslab_fragmentation(ms);
|
||||
ms->ms_ops = mg->mg_class->mc_ops;
|
||||
|
||||
/*
|
||||
* If we're opening an existing pool (txg == 0) or creating
|
||||
@ -1341,25 +1349,27 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg)
|
||||
* does not become available until after this txg has synced.
|
||||
*/
|
||||
if (txg <= TXG_INITIAL)
|
||||
metaslab_sync_done(msp, 0);
|
||||
metaslab_sync_done(ms, 0);
|
||||
|
||||
/*
|
||||
* If metaslab_debug_load is set and we're initializing a metaslab
|
||||
* that has an allocated space_map object then load the its space
|
||||
* map so that can verify frees.
|
||||
*/
|
||||
if (metaslab_debug_load && msp->ms_sm != NULL) {
|
||||
mutex_enter(&msp->ms_lock);
|
||||
VERIFY0(metaslab_load(msp));
|
||||
mutex_exit(&msp->ms_lock);
|
||||
if (metaslab_debug_load && ms->ms_sm != NULL) {
|
||||
mutex_enter(&ms->ms_lock);
|
||||
VERIFY0(metaslab_load(ms));
|
||||
mutex_exit(&ms->ms_lock);
|
||||
}
|
||||
|
||||
if (txg != 0) {
|
||||
vdev_dirty(vd, 0, NULL, txg);
|
||||
vdev_dirty(vd, VDD_METASLAB, msp, txg);
|
||||
vdev_dirty(vd, VDD_METASLAB, ms, txg);
|
||||
}
|
||||
|
||||
return (msp);
|
||||
*msp = ms;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -42,8 +42,8 @@ typedef struct metaslab_ops {
|
||||
|
||||
extern metaslab_ops_t *zfs_metaslab_ops;
|
||||
|
||||
metaslab_t *metaslab_init(metaslab_group_t *, uint64_t,
|
||||
uint64_t, uint64_t);
|
||||
int metaslab_init(metaslab_group_t *, uint64_t, uint64_t, uint64_t,
|
||||
metaslab_t **);
|
||||
void metaslab_fini(metaslab_t *);
|
||||
|
||||
void metaslab_load_wait(metaslab_t *);
|
||||
|
@ -955,7 +955,11 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg)
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
vd->vdev_ms[m] = metaslab_init(vd->vdev_mg, m, object, txg);
|
||||
|
||||
error = metaslab_init(vd->vdev_mg, m, object, txg,
|
||||
&(vd->vdev_ms[m]));
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (txg == 0)
|
||||
|
@ -336,6 +336,8 @@ dev/viawd/viawd.c optional viawd
|
||||
dev/vmware/vmxnet3/if_vmx.c optional vmx
|
||||
dev/wbwd/wbwd.c optional wbwd
|
||||
dev/wpi/if_wpi.c optional wpi
|
||||
dev/xen/pci/xen_acpi_pci.c optional xenhvm
|
||||
dev/xen/pci/xen_pci.c optional xenhvm
|
||||
dev/isci/isci.c optional isci
|
||||
dev/isci/isci_controller.c optional isci
|
||||
dev/isci/isci_domain.c optional isci
|
||||
@ -572,4 +574,4 @@ x86/xen/xen_apic.c optional xenhvm
|
||||
x86/xen/xenpv.c optional xenhvm
|
||||
x86/xen/xen_nexus.c optional xenhvm
|
||||
x86/xen/xen_msi.c optional xenhvm
|
||||
x86/xen/xen_pci.c optional xenhvm
|
||||
x86/xen/xen_pci_bus.c optional xenhvm
|
||||
|
655
sys/dev/beri/virtio/network/if_vtbe.c
Normal file
655
sys/dev/beri/virtio/network/if_vtbe.c
Normal file
@ -0,0 +1,655 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BERI Virtio Networking Frontend
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mdioctl.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/beri/virtio/virtio.h>
|
||||
#include <dev/beri/virtio/virtio_mmio_platform.h>
|
||||
|
||||
#include <dev/altera/pio/pio.h>
|
||||
|
||||
#include <dev/virtio/mmio/virtio_mmio.h>
|
||||
#include <dev/virtio/network/virtio_net.h>
|
||||
#include <dev/virtio/virtio.h>
|
||||
#include <dev/virtio/virtio_ring.h>
|
||||
|
||||
#include "pio_if.h"
|
||||
|
||||
#define DPRINTF(fmt, args...) printf(fmt, ##args)
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_read_4((_sc)->res[0], _reg)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_write_4((_sc)->res[0], _reg, _val)
|
||||
|
||||
#define VTBE_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define VTBE_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define VTBE_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED);
|
||||
#define VTBE_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED);
|
||||
|
||||
/*
|
||||
* Driver data and defines.
|
||||
*/
|
||||
#define DESC_COUNT 256
|
||||
|
||||
struct vtbe_softc {
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
struct ifnet *ifp;
|
||||
int if_flags;
|
||||
struct mtx mtx;
|
||||
boolean_t is_attached;
|
||||
|
||||
int beri_mem_offset;
|
||||
device_t pio_send;
|
||||
device_t pio_recv;
|
||||
int opened;
|
||||
|
||||
struct vqueue_info vs_queues[2];
|
||||
int vs_curq;
|
||||
int hdrsize;
|
||||
};
|
||||
|
||||
static struct resource_spec vtbe_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static void vtbe_txfinish_locked(struct vtbe_softc *sc);
|
||||
static void vtbe_rxfinish_locked(struct vtbe_softc *sc);
|
||||
static void vtbe_stop_locked(struct vtbe_softc *sc);
|
||||
static int pio_enable_irq(struct vtbe_softc *sc, int enable);
|
||||
|
||||
static void
|
||||
vtbe_txstart_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct virtio_net_hdr_mrg_rxbuf *vnh;
|
||||
struct iovec iov[DESC_COUNT];
|
||||
struct vqueue_info *vq;
|
||||
struct iovec *riov;
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m;
|
||||
struct uio uio;
|
||||
int enqueued;
|
||||
int iolen;
|
||||
int error;
|
||||
int *addr;
|
||||
int reg;
|
||||
int len;
|
||||
int n;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
/* RX queue */
|
||||
vq = &sc->vs_queues[0];
|
||||
if (!vq_has_descs(vq)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = sc->ifp;
|
||||
if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
enqueued = 0;
|
||||
|
||||
if (!vq_ring_ready(vq))
|
||||
return;
|
||||
|
||||
vq->vq_save_used = be16toh(vq->vq_used->idx);
|
||||
|
||||
for (;;) {
|
||||
if (!vq_has_descs(vq)) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
n = vq_getchain(sc->beri_mem_offset, vq, iov,
|
||||
DESC_COUNT, NULL);
|
||||
|
||||
KASSERT(n >= 1 && n <= DESC_COUNT,
|
||||
("wrong descriptors num %d", n));
|
||||
|
||||
addr = iov[0].iov_base;
|
||||
len = iov[0].iov_len;
|
||||
|
||||
vnh = iov[0].iov_base;
|
||||
memset(vnh, 0, sc->hdrsize);
|
||||
vnh->num_buffers = htobe16(1);
|
||||
|
||||
iov[0].iov_len -= sc->hdrsize;
|
||||
iov[0].iov_base = (void *)((uintptr_t)iov[0].iov_base +
|
||||
sc->hdrsize);
|
||||
riov = &iov[0];
|
||||
|
||||
uio.uio_resid = iov[0].iov_len;
|
||||
uio.uio_iov = riov;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_rw = UIO_READ;
|
||||
|
||||
error = m_mbuftouio(&uio, m, 0);
|
||||
if (error)
|
||||
panic("m_mbuftouio failed\n");
|
||||
|
||||
iolen = (len - iov[0].iov_len - sc->hdrsize);
|
||||
vq_relchain(vq, iov, 0, iolen + sc->hdrsize);
|
||||
paddr_unmap((void *)addr, len);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
BPF_MTAP(ifp, m);
|
||||
m_freem(m);
|
||||
|
||||
++enqueued;
|
||||
}
|
||||
|
||||
if (enqueued != 0) {
|
||||
reg = htobe32(VIRTIO_MMIO_INT_VRING);
|
||||
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
|
||||
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_txstart(struct ifnet *ifp)
|
||||
{
|
||||
struct vtbe_softc *sc = ifp->if_softc;
|
||||
|
||||
VTBE_LOCK(sc);
|
||||
vtbe_txstart_locked(sc);
|
||||
VTBE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_stop_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
ifp = sc->ifp;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_init_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->ifp;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
return;
|
||||
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_init(void *if_softc)
|
||||
{
|
||||
struct vtbe_softc *sc = if_softc;
|
||||
|
||||
VTBE_LOCK(sc);
|
||||
vtbe_init_locked(sc);
|
||||
VTBE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct ifmediareq *ifmr;
|
||||
struct vtbe_softc *sc;
|
||||
struct ifreq *ifr;
|
||||
int mask, error;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
ifr = (struct ifreq *)data;
|
||||
|
||||
error = 0;
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
VTBE_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
pio_enable_irq(sc, 1);
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
vtbe_init_locked(sc);
|
||||
}
|
||||
} else {
|
||||
pio_enable_irq(sc, 0);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
vtbe_stop_locked(sc);
|
||||
}
|
||||
}
|
||||
sc->if_flags = ifp->if_flags;
|
||||
VTBE_UNLOCK(sc);
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
break;
|
||||
case SIOCSIFMEDIA:
|
||||
case SIOCGIFMEDIA:
|
||||
ifmr = (struct ifmediareq *)data;
|
||||
ifmr->ifm_count = 1;
|
||||
ifmr->ifm_status = (IFM_AVALID | IFM_ACTIVE);
|
||||
ifmr->ifm_active = (IFM_ETHER | IFM_10G_T | IFM_FDX);
|
||||
ifmr->ifm_current = ifmr->ifm_active;
|
||||
break;
|
||||
case SIOCSIFCAP:
|
||||
mask = ifp->if_capenable ^ ifr->ifr_reqcap;
|
||||
if (mask & IFCAP_VLAN_MTU) {
|
||||
ifp->if_capenable ^= IFCAP_VLAN_MTU;
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR:
|
||||
pio_enable_irq(sc, 1);
|
||||
default:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_txfinish_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
ifp = sc->ifp;
|
||||
}
|
||||
|
||||
static int
|
||||
vq_init(struct vtbe_softc *sc)
|
||||
{
|
||||
struct vqueue_info *vq;
|
||||
uint8_t *base;
|
||||
int size;
|
||||
int reg;
|
||||
int pfn;
|
||||
|
||||
vq = &sc->vs_queues[sc->vs_curq];
|
||||
vq->vq_qsize = DESC_COUNT;
|
||||
|
||||
reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN);
|
||||
pfn = be32toh(reg);
|
||||
vq->vq_pfn = pfn;
|
||||
|
||||
size = vring_size(vq->vq_qsize, VRING_ALIGN);
|
||||
base = paddr_map(sc->beri_mem_offset,
|
||||
(pfn << PAGE_SHIFT), size);
|
||||
|
||||
/* First pages are descriptors */
|
||||
vq->vq_desc = (struct vring_desc *)base;
|
||||
base += vq->vq_qsize * sizeof(struct vring_desc);
|
||||
|
||||
/* Then avail ring */
|
||||
vq->vq_avail = (struct vring_avail *)base;
|
||||
base += (2 + vq->vq_qsize + 1) * sizeof(uint16_t);
|
||||
|
||||
/* Then it's rounded up to the next page */
|
||||
base = (uint8_t *)roundup2((uintptr_t)base, VRING_ALIGN);
|
||||
|
||||
/* And the last pages are the used ring */
|
||||
vq->vq_used = (struct vring_used *)base;
|
||||
|
||||
/* Mark queue as allocated, and start at 0 when we use it. */
|
||||
vq->vq_flags = VQ_ALLOC;
|
||||
vq->vq_last_avail = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_proc_rx(struct vtbe_softc *sc, struct vqueue_info *vq)
|
||||
{
|
||||
struct iovec iov[DESC_COUNT];
|
||||
struct ifnet *ifp;
|
||||
struct uio uio;
|
||||
struct mbuf *m;
|
||||
int iolen;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
ifp = sc->ifp;
|
||||
|
||||
n = vq_getchain(sc->beri_mem_offset, vq, iov,
|
||||
DESC_COUNT, NULL);
|
||||
|
||||
KASSERT(n >= 1 && n <= DESC_COUNT,
|
||||
("wrong n %d", n));
|
||||
|
||||
iolen = 0;
|
||||
for (i = 1; i < n; i++) {
|
||||
iolen += iov[i].iov_len;
|
||||
}
|
||||
|
||||
uio.uio_resid = iolen;
|
||||
uio.uio_iov = &iov[1];
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_iovcnt = (n - 1);
|
||||
uio.uio_rw = UIO_WRITE;
|
||||
|
||||
if ((m = m_uiotombuf(&uio, M_NOWAIT, 0, ETHER_ALIGN,
|
||||
M_PKTHDR)) == NULL) {
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto done;
|
||||
}
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
VTBE_UNLOCK(sc);
|
||||
(*ifp->if_input)(ifp, m);
|
||||
VTBE_LOCK(sc);
|
||||
CURVNET_RESTORE();
|
||||
|
||||
done:
|
||||
vq_relchain(vq, iov, n, iolen + sc->hdrsize);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_rxfinish_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct vqueue_info *vq;
|
||||
int reg;
|
||||
|
||||
/* TX queue */
|
||||
vq = &sc->vs_queues[1];
|
||||
if (!vq_ring_ready(vq))
|
||||
return;
|
||||
|
||||
/* Process new descriptors */
|
||||
vq->vq_save_used = be16toh(vq->vq_used->idx);
|
||||
|
||||
while (vq_has_descs(vq)) {
|
||||
vtbe_proc_rx(sc, vq);
|
||||
}
|
||||
|
||||
/* Interrupt the other side */
|
||||
reg = htobe32(VIRTIO_MMIO_INT_VRING);
|
||||
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
|
||||
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_intr(void *arg)
|
||||
{
|
||||
struct vtbe_softc *sc;
|
||||
int pending;
|
||||
uint32_t reg;
|
||||
|
||||
sc = arg;
|
||||
|
||||
VTBE_LOCK(sc);
|
||||
|
||||
reg = PIO_READ(sc->pio_recv);
|
||||
|
||||
/* Ack */
|
||||
PIO_SET(sc->pio_recv, reg, 0);
|
||||
|
||||
pending = htobe32(reg);
|
||||
if (pending & Q_SEL) {
|
||||
reg = READ4(sc, VIRTIO_MMIO_QUEUE_SEL);
|
||||
sc->vs_curq = be32toh(reg);
|
||||
}
|
||||
|
||||
if (pending & Q_PFN) {
|
||||
vq_init(sc);
|
||||
}
|
||||
|
||||
if (pending & Q_NOTIFY) {
|
||||
/* beri rx / arm tx notify */
|
||||
vtbe_txfinish_locked(sc);
|
||||
}
|
||||
|
||||
if (pending & Q_NOTIFY1) {
|
||||
vtbe_rxfinish_locked(sc);
|
||||
}
|
||||
|
||||
VTBE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_get_hwaddr(struct vtbe_softc *sc, uint8_t *hwaddr)
|
||||
{
|
||||
int rnd;
|
||||
|
||||
/*
|
||||
* Generate MAC address, use 'bsd' + random 24 low-order bits.
|
||||
*/
|
||||
|
||||
rnd = arc4random() & 0x00ffffff;
|
||||
|
||||
hwaddr[0] = 'b';
|
||||
hwaddr[1] = 's';
|
||||
hwaddr[2] = 'd';
|
||||
hwaddr[3] = rnd >> 16;
|
||||
hwaddr[4] = rnd >> 8;
|
||||
hwaddr[5] = rnd >> 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_enable_irq(struct vtbe_softc *sc, int enable)
|
||||
{
|
||||
|
||||
/*
|
||||
* IRQ lines should be disabled while reprogram FPGA core.
|
||||
*/
|
||||
|
||||
if (enable) {
|
||||
if (sc->opened == 0) {
|
||||
sc->opened = 1;
|
||||
PIO_SETUP_IRQ(sc->pio_recv, vtbe_intr, sc);
|
||||
}
|
||||
} else {
|
||||
if (sc->opened == 1) {
|
||||
PIO_TEARDOWN_IRQ(sc->pio_recv);
|
||||
sc->opened = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-vtnet"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Virtio BERI Ethernet Controller");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_attach(device_t dev)
|
||||
{
|
||||
uint8_t macaddr[ETHER_ADDR_LEN];
|
||||
struct vtbe_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int reg;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
sc->hdrsize = sizeof(struct virtio_net_hdr_mrg_rxbuf);
|
||||
|
||||
if (bus_alloc_resources(dev, vtbe_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
|
||||
if (setup_offset(dev, &sc->beri_mem_offset) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(dev, "pio-send", &sc->pio_send) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(dev, "pio-recv", &sc->pio_recv) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
/* Setup MMIO */
|
||||
|
||||
/* Specify that we provide network device */
|
||||
reg = htobe32(VIRTIO_ID_NETWORK);
|
||||
WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg);
|
||||
|
||||
/* The number of desc we support */
|
||||
reg = htobe32(DESC_COUNT);
|
||||
WRITE4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX, reg);
|
||||
|
||||
/* Our features */
|
||||
reg = htobe32(VIRTIO_NET_F_MAC |
|
||||
VIRTIO_NET_F_MRG_RXBUF |
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
WRITE4(sc, VIRTIO_MMIO_HOST_FEATURES, reg);
|
||||
|
||||
/* Get MAC */
|
||||
if (vtbe_get_hwaddr(sc, macaddr)) {
|
||||
device_printf(sc->dev, "can't get mac\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Set up the ethernet interface. */
|
||||
sc->ifp = ifp = if_alloc(IFT_ETHER);
|
||||
ifp->if_baudrate = IF_Gbps(10);
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
||||
ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX |
|
||||
IFF_MULTICAST | IFF_PROMISC);
|
||||
ifp->if_capabilities = IFCAP_VLAN_MTU;
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
ifp->if_start = vtbe_txstart;
|
||||
ifp->if_ioctl = vtbe_ioctl;
|
||||
ifp->if_init = vtbe_init;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, DESC_COUNT - 1);
|
||||
ifp->if_snd.ifq_drv_maxlen = DESC_COUNT - 1;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
|
||||
|
||||
/* All ready to run, attach the ethernet interface. */
|
||||
ether_ifattach(ifp, macaddr);
|
||||
|
||||
sc->is_attached = true;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t vtbe_methods[] = {
|
||||
DEVMETHOD(device_probe, vtbe_probe),
|
||||
DEVMETHOD(device_attach, vtbe_attach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t vtbe_driver = {
|
||||
"vtbe",
|
||||
vtbe_methods,
|
||||
sizeof(struct vtbe_softc),
|
||||
};
|
||||
|
||||
static devclass_t vtbe_devclass;
|
||||
|
||||
DRIVER_MODULE(vtbe, simplebus, vtbe_driver, vtbe_devclass, 0, 0);
|
||||
MODULE_DEPEND(vtbe, ether, 1, 1, 1);
|
@ -58,10 +58,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/beri/virtio/virtio.h>
|
||||
#include <dev/virtio/virtio.h>
|
||||
#include <dev/virtio/virtqueue.h>
|
||||
#include <dev/virtio/virtio_ring.h>
|
||||
#include <dev/altera/pio/pio.h>
|
||||
|
||||
#include "pio_if.h"
|
||||
|
||||
int
|
||||
vq_ring_ready(struct vqueue_info *vq)
|
||||
@ -167,12 +175,13 @@ vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen)
|
||||
int i;
|
||||
|
||||
mask = vq->vq_qsize - 1;
|
||||
vu = vq->vq_used;
|
||||
head = be16toh(vq->vq_avail->ring[vq->vq_last_avail++ & mask]);
|
||||
|
||||
vu = vq->vq_used;
|
||||
uidx = be16toh(vu->idx);
|
||||
vue = &vu->ring[uidx++ & mask];
|
||||
vue->id = htobe16(head);
|
||||
vue->id = htobe32(head);
|
||||
|
||||
vue->len = htobe32(iolen);
|
||||
vu->idx = htobe16(uidx);
|
||||
|
||||
@ -181,3 +190,59 @@ vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen)
|
||||
paddr_unmap((void *)iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
setup_pio(device_t dev, char *name, device_t *pio_dev)
|
||||
{
|
||||
phandle_t pio_node;
|
||||
struct fdt_ic *ic;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
|
||||
if ((node = ofw_bus_get_node(dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, name, &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
pio_node = OF_node_from_xref(xref);
|
||||
SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
|
||||
if (ic->iph == pio_node) {
|
||||
*pio_dev = ic->dev;
|
||||
PIO_CONFIGURE(*pio_dev, PIO_OUT_ALL,
|
||||
PIO_UNMASK_ALL);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
setup_offset(device_t dev, uint32_t *offset)
|
||||
{
|
||||
pcell_t dts_value[2];
|
||||
phandle_t mem_node;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
int len;
|
||||
|
||||
if ((node = ofw_bus_get_node(dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, "beri-mem", &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mem_node = OF_node_from_xref(xref);
|
||||
if ((len = OF_getproplen(mem_node, "reg")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(mem_node, "reg", dts_value, len);
|
||||
*offset = dts_value[0];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -41,14 +41,10 @@
|
||||
|
||||
#define PAGE_SHIFT 12
|
||||
#define VRING_ALIGN 4096
|
||||
#define NUM_QUEUES 1
|
||||
|
||||
#define VQ_ALLOC 0x01 /* set once we have a pfn */
|
||||
#define VQ_MAX_DESCRIPTORS 512
|
||||
|
||||
#define VTBLK_BLK_ID_BYTES 20
|
||||
#define VTBLK_MAXSEGS 256
|
||||
|
||||
struct vqueue_info {
|
||||
uint16_t vq_qsize; /* size of this queue (a power of 2) */
|
||||
uint16_t vq_num;
|
||||
@ -70,3 +66,5 @@ int vq_getchain(uint32_t beri_mem_offset, struct vqueue_info *vq,
|
||||
struct iovec *iov, int n_iov, uint16_t *flags);
|
||||
void vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen);
|
||||
|
||||
int setup_pio(device_t dev, char *name, device_t *pio_dev);
|
||||
int setup_offset(device_t dev, uint32_t *offset);
|
||||
|
@ -74,6 +74,13 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define DPRINTF(fmt, ...)
|
||||
|
||||
/* We use indirect descriptors */
|
||||
#define NUM_DESCS 1
|
||||
#define NUM_QUEUES 1
|
||||
|
||||
#define VTBLK_BLK_ID_BYTES 20
|
||||
#define VTBLK_MAXSEGS 256
|
||||
|
||||
struct beri_vtblk_softc {
|
||||
struct resource *res[1];
|
||||
bus_space_tag_t bst;
|
||||
@ -286,8 +293,12 @@ vtblk_notify(struct beri_vtblk_softc *sc)
|
||||
while (vq_has_descs(vq))
|
||||
vtblk_proc(sc, vq);
|
||||
|
||||
/* Interrupt other side */
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
/* Interrupt the other side */
|
||||
if ((be16toh(vq->vq_avail->flags) & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
|
||||
reg = htobe32(VIRTIO_MMIO_INT_VRING);
|
||||
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -302,7 +313,7 @@ vq_init(struct beri_vtblk_softc *sc)
|
||||
int pfn;
|
||||
|
||||
vq = &sc->vs_queues[0];
|
||||
vq->vq_qsize = NUM_QUEUES;
|
||||
vq->vq_qsize = NUM_DESCS;
|
||||
|
||||
reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN);
|
||||
pfn = be32toh(reg);
|
||||
@ -352,61 +363,6 @@ vtblk_thread(void *arg)
|
||||
kthread_exit();
|
||||
}
|
||||
|
||||
static int
|
||||
setup_pio(struct beri_vtblk_softc *sc, char *name, device_t *dev)
|
||||
{
|
||||
phandle_t pio_node;
|
||||
struct fdt_ic *ic;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, name, &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
pio_node = OF_node_from_xref(xref);
|
||||
SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
|
||||
if (ic->iph == pio_node) {
|
||||
*dev = ic->dev;
|
||||
PIO_CONFIGURE(*dev, PIO_OUT_ALL,
|
||||
PIO_UNMASK_ALL);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
setup_offset(struct beri_vtblk_softc *sc)
|
||||
{
|
||||
pcell_t dts_value[2];
|
||||
phandle_t mem_node;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
int len;
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, "beri-mem", &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mem_node = OF_node_from_xref(xref);
|
||||
if ((len = OF_getproplen(mem_node, "reg")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(mem_node, "reg", dts_value, len);
|
||||
sc->beri_mem_offset = dts_value[0];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
backend_info(struct beri_vtblk_softc *sc)
|
||||
{
|
||||
@ -419,9 +375,9 @@ backend_info(struct beri_vtblk_softc *sc)
|
||||
reg = htobe32(VIRTIO_ID_BLOCK);
|
||||
WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg);
|
||||
|
||||
/* The number of queues we support */
|
||||
reg = htobe16(NUM_QUEUES);
|
||||
WRITE2(sc, VIRTIO_MMIO_QUEUE_NUM, reg);
|
||||
/* Queue size */
|
||||
reg = htobe32(NUM_DESCS);
|
||||
WRITE4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX, reg);
|
||||
|
||||
/* Our features */
|
||||
reg = htobe32(VIRTIO_RING_F_INDIRECT_DESC
|
||||
@ -566,11 +522,11 @@ beri_vtblk_attach(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (setup_offset(sc) != 0)
|
||||
if (setup_offset(dev, &sc->beri_mem_offset) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(sc, "pio-send", &sc->pio_send) != 0)
|
||||
if (setup_pio(dev, "pio-send", &sc->pio_send) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(sc, "pio-recv", &sc->pio_recv) != 0)
|
||||
if (setup_pio(dev, "pio-recv", &sc->pio_recv) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
sc->cdev = make_dev(&beri_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
|
@ -149,20 +149,49 @@ virtio_mmio_platform_attach(device_t dev)
|
||||
}
|
||||
|
||||
static int
|
||||
platform_note(device_t dev, size_t offset)
|
||||
platform_note(device_t dev, size_t offset, int val)
|
||||
{
|
||||
struct virtio_mmio_platform_softc *sc;
|
||||
int note;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (offset == VIRTIO_MMIO_QUEUE_NOTIFY) {
|
||||
mips_dcache_wbinv_all();
|
||||
PIO_SET(sc->pio_send, Q_NOTIFY, 1);
|
||||
switch (offset) {
|
||||
case (VIRTIO_MMIO_QUEUE_NOTIFY):
|
||||
if (val == 0)
|
||||
note = Q_NOTIFY;
|
||||
else if (val == 1)
|
||||
note = Q_NOTIFY1;
|
||||
break;
|
||||
case (VIRTIO_MMIO_QUEUE_PFN):
|
||||
note = Q_PFN;
|
||||
break;
|
||||
case (VIRTIO_MMIO_QUEUE_SEL):
|
||||
note = Q_SEL;
|
||||
break;
|
||||
default:
|
||||
note = 0;
|
||||
}
|
||||
|
||||
if (offset == VIRTIO_MMIO_QUEUE_PFN) {
|
||||
if (note) {
|
||||
mips_dcache_wbinv_all();
|
||||
PIO_SET(sc->pio_send, Q_PFN, 1);
|
||||
|
||||
PIO_SET(sc->pio_send, note, 1);
|
||||
|
||||
/*
|
||||
* Wait until host ack the request.
|
||||
* Usually done within few cycles.
|
||||
* TODO: bad
|
||||
*/
|
||||
|
||||
for (i = 100; i > 0; i--) {
|
||||
if (PIO_READ(sc->pio_send) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
device_printf(sc->dev, "Warning: host busy\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
@ -30,6 +30,8 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define Q_NOTIFY 0x1
|
||||
#define Q_PFN 0x2
|
||||
#define Q_INTR 0x4
|
||||
#define Q_NOTIFY 0x01
|
||||
#define Q_PFN 0x02
|
||||
#define Q_INTR 0x04
|
||||
#define Q_SEL 0x08
|
||||
#define Q_NOTIFY1 0x10
|
||||
|
@ -252,6 +252,7 @@ xhci_pci_attach(device_t self)
|
||||
case 0x9c318086: /* Panther Point */
|
||||
case 0x1e318086: /* Panther Point */
|
||||
case 0x8c318086: /* Lynx Point */
|
||||
case 0x8cb18086: /* Wildcat Point */
|
||||
sc->sc_port_route = &xhci_pci_port_route;
|
||||
sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP;
|
||||
break;
|
||||
|
@ -59,7 +59,7 @@
|
||||
MODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
|
||||
MODULE_VERSION(usb_quirk, 1);
|
||||
|
||||
#define USB_DEV_QUIRKS_MAX 320
|
||||
#define USB_DEV_QUIRKS_MAX 384
|
||||
#define USB_SUB_QUIRKS_MAX 8
|
||||
|
||||
struct usb_quirk_entry {
|
||||
@ -438,8 +438,27 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
USB_QUIRK(WESTERN, MYBOOK, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY_EVPD,
|
||||
UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSWORD, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_00, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_03, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_04, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_05, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_06, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_07, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT_10, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_00, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_03, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_04, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_05, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_06, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_07, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSPORTES_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WINMAXGROUP, FLASH64MC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(YANO, FW800HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
|
@ -400,7 +400,11 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
|
||||
U3G_DEV(QUALCOMM2, VW110L, U3GINIT_SCSIEJECT),
|
||||
U3G_DEV(QUALCOMM2, GOBI2000_QDL, 0),
|
||||
U3G_DEV(QUALCOMM2, GOBI2000, 0),
|
||||
U3G_DEV(QUALCOMM2, VT80N, 0),
|
||||
U3G_DEV(QUALCOMM3, VFAST2, 0),
|
||||
U3G_DEV(QUALCOMMINC, AC2726, 0),
|
||||
U3G_DEV(QUALCOMMINC, AC682_INIT, U3GINIT_SCSIEJECT),
|
||||
U3G_DEV(QUALCOMMINC, AC682, 0),
|
||||
U3G_DEV(QUALCOMMINC, AC8700, 0),
|
||||
U3G_DEV(QUALCOMMINC, AC8710, 0),
|
||||
U3G_DEV(QUALCOMMINC, CDMA_MSM, U3GINIT_SCSIEJECT),
|
||||
|
@ -695,6 +695,7 @@ vendor QCOM 0x18e8 Qcom
|
||||
vendor ELV 0x18ef ELV
|
||||
vendor LINKSYS3 0x1915 Linksys
|
||||
vendor QUALCOMMINC 0x19d2 Qualcomm, Incorporated
|
||||
vendor QUALCOMM3 0x19f5 Qualcomm, Inc.
|
||||
vendor BAYER 0x1a79 Bayer
|
||||
vendor WCH2 0x1a86 QinHeng Electronics
|
||||
vendor STELERA 0x1a8d Stelera Wireless
|
||||
@ -3194,7 +3195,7 @@ product NETGEAR EA101X 0x1002 Ethernet
|
||||
product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1
|
||||
product NETGEAR FA120 0x1040 USB 2.0 Ethernet
|
||||
product NETGEAR M4100 0x1100 M4100/M5300/M7100 series switch
|
||||
product NETGEAR WG111V2_2 0x4240 PrismGT USB 2.0 WLAN
|
||||
product NETGEAR WG111V1_2 0x4240 PrismGT USB 2.0 WLAN
|
||||
product NETGEAR WG111V3 0x4260 WG111v3
|
||||
product NETGEAR WG111U 0x4300 WG111U
|
||||
product NETGEAR WG111U_NF 0x4301 WG111U (no firmware)
|
||||
@ -3574,6 +3575,8 @@ product QUALCOMM2 VW110L 0x1000 Vertex Wireless 110L modem
|
||||
product QUALCOMM2 SIM5218 0x9000 SIM5218
|
||||
product QUALCOMM2 GOBI2000_QDL 0x9204 Qualcomm Gobi 2000 QDL
|
||||
product QUALCOMM2 GOBI2000 0x9205 Qualcomm Gobi 2000 modem
|
||||
product QUALCOMM2 VT80N 0x6500 Venus VT80N
|
||||
product QUALCOMM3 VFAST2 0x9909 Venus Fast2 modem
|
||||
product QUALCOMMINC CDMA_MSM 0x0001 CDMA Technologies MSM modem
|
||||
product QUALCOMMINC E0002 0x0002 3G modem
|
||||
product QUALCOMMINC E0003 0x0003 3G modem
|
||||
@ -3648,6 +3651,8 @@ product QUALCOMMINC MF195E 0x1516 MF195E
|
||||
product QUALCOMMINC ZTE_STOR 0x2000 USB ZTE Storage
|
||||
product QUALCOMMINC E2002 0x2002 3G modem
|
||||
product QUALCOMMINC E2003 0x2003 3G modem
|
||||
product QUALCOMMINC AC682 0xffdd CDMA 1xEVDO USB modem
|
||||
product QUALCOMMINC AC682_INIT 0xffde CDMA 1xEVDO USB modem (initial)
|
||||
product QUALCOMMINC AC8710 0xfff1 3G modem
|
||||
product QUALCOMMINC AC2726 0xfff5 3G modem
|
||||
product QUALCOMMINC AC8700 0xfffe CDMA 1xEVDO USB modem
|
||||
@ -4486,8 +4491,27 @@ product WESTERN COMBO 0x0200 Firewire USB Combo
|
||||
product WESTERN EXTHDD 0x0400 External HDD
|
||||
product WESTERN HUB 0x0500 USB HUB
|
||||
product WESTERN MYBOOK 0x0901 MyBook External HDD
|
||||
product WESTERN MYPASSWORD 0x0704 MyPassword External HDD
|
||||
product WESTERN MYPASSPORT 0x0748 MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_00 0x0704 MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_01 0x0746 MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_02 0x0748 MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_03 0x074A MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_04 0x074C MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_05 0x074E MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_06 0x07A6 MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_07 0x07A8 MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_08 0x07AA MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_09 0x07AC MyPassport External HDD
|
||||
product WESTERN MYPASSPORT_10 0x07AE MyPassport External HDD
|
||||
product WESTERN MYPASSPORTES_00 0x070A MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_01 0x071A MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_02 0x0730 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_03 0x0732 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_04 0x0740 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_05 0x0742 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_06 0x0750 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_07 0x0752 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_08 0x07A0 MyPassport Essential External HDD
|
||||
product WESTERN MYPASSPORTES_09 0x07A2 MyPassport Essential External HDD
|
||||
|
||||
/* WeTelecom products */
|
||||
product WETELECOM WM_D200 0x6801 WM-D200
|
||||
|
@ -182,7 +182,7 @@ static const STRUCT_USB_HOST_ID upgt_devs[] = {
|
||||
UPGT_DEV(FSC, E5400),
|
||||
UPGT_DEV(GLOBESPAN, PRISM_GT_1),
|
||||
UPGT_DEV(GLOBESPAN, PRISM_GT_2),
|
||||
UPGT_DEV(NETGEAR, WG111V2_2),
|
||||
UPGT_DEV(NETGEAR, WG111V1_2),
|
||||
UPGT_DEV(INTERSIL, PRISM_GT),
|
||||
UPGT_DEV(SMC, 2862WG),
|
||||
UPGT_DEV(USR, USR5422),
|
||||
|
@ -1,11 +1,15 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2014 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Portions of this software were developed by Andrew Turner
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -131,15 +135,24 @@ static void vtmmio_vq_intr(void *);
|
||||
/*
|
||||
* I/O port read/write wrappers.
|
||||
*/
|
||||
#define vtmmio_write_config_1(sc, o, v) \
|
||||
bus_write_1((sc)->res[0], (o), (v)); \
|
||||
VIRTIO_MMIO_NOTE(sc->platform, (o))
|
||||
#define vtmmio_write_config_2(sc, o, v) \
|
||||
bus_write_2((sc)->res[0], (o), (v)); \
|
||||
VIRTIO_MMIO_NOTE(sc->platform, (o))
|
||||
#define vtmmio_write_config_4(sc, o, v) \
|
||||
bus_write_4((sc)->res[0], (o), (v)); \
|
||||
VIRTIO_MMIO_NOTE(sc->platform, (o))
|
||||
#define vtmmio_write_config_1(sc, o, v) \
|
||||
do { \
|
||||
bus_write_1((sc)->res[0], (o), (v)); \
|
||||
if (sc->platform != NULL) \
|
||||
VIRTIO_MMIO_NOTE(sc->platform, (o), (v)); \
|
||||
} while (0)
|
||||
#define vtmmio_write_config_2(sc, o, v) \
|
||||
do { \
|
||||
bus_write_2((sc)->res[0], (o), (v)); \
|
||||
if (sc->platform != NULL) \
|
||||
VIRTIO_MMIO_NOTE(sc->platform, (o), (v)); \
|
||||
} while (0)
|
||||
#define vtmmio_write_config_4(sc, o, v) \
|
||||
do { \
|
||||
bus_write_4((sc)->res[0], (o), (v)); \
|
||||
if (sc->platform != NULL) \
|
||||
VIRTIO_MMIO_NOTE(sc->platform, (o), (v)); \
|
||||
} while (0)
|
||||
|
||||
#define vtmmio_read_config_1(sc, o) \
|
||||
bus_read_1((sc)->res[0], (o))
|
||||
@ -200,11 +213,13 @@ vtmmio_setup_intr(device_t dev, enum intr_type type)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev,
|
||||
vtmmio_vq_intr, sc);
|
||||
if (err == 0) {
|
||||
/* Okay we have backend-specific interrupts */
|
||||
return (0);
|
||||
if (sc->platform != NULL) {
|
||||
err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev,
|
||||
vtmmio_vq_intr, sc);
|
||||
if (err == 0) {
|
||||
/* Okay we have backend-specific interrupts */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
rid = 0;
|
||||
@ -473,8 +488,8 @@ vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
|
||||
struct vq_alloc_info *info;
|
||||
struct vtmmio_softc *sc;
|
||||
struct virtqueue *vq;
|
||||
uint32_t size;
|
||||
int idx, error;
|
||||
uint16_t size;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
@ -492,8 +507,10 @@ vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
|
||||
vqx = &sc->vtmmio_vqs[idx];
|
||||
info = &vq_info[idx];
|
||||
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
|
||||
|
||||
vtmmio_select_virtqueue(sc, idx);
|
||||
size = vtmmio_read_config_2(sc, VIRTIO_MMIO_QUEUE_NUM);
|
||||
size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
|
||||
|
||||
error = virtqueue_alloc(dev, idx, size,
|
||||
VIRTIO_MMIO_VRING_ALIGN, 0xFFFFFFFFUL, info, &vq);
|
||||
@ -503,6 +520,10 @@ vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
|
||||
idx, error);
|
||||
break;
|
||||
}
|
||||
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NUM, size);
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_ALIGN,
|
||||
VIRTIO_MMIO_VRING_ALIGN);
|
||||
#if 0
|
||||
device_printf(dev, "virtqueue paddr 0x%08lx\n",
|
||||
(uint64_t)virtqueue_paddr(vq));
|
||||
@ -572,7 +593,7 @@ vtmmio_notify_virtqueue(device_t dev, uint16_t queue)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
vtmmio_write_config_2(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue);
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
@ -582,7 +603,7 @@ vtmmio_get_status(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
return (vtmmio_read_config_1(sc, VIRTIO_MMIO_STATUS));
|
||||
return (vtmmio_read_config_4(sc, VIRTIO_MMIO_STATUS));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -595,7 +616,7 @@ vtmmio_set_status(device_t dev, uint8_t status)
|
||||
if (status != VIRTIO_CONFIG_STATUS_RESET)
|
||||
status |= vtmmio_get_status(dev);
|
||||
|
||||
vtmmio_write_config_1(sc, VIRTIO_MMIO_STATUS, status);
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_STATUS, status);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -611,13 +632,16 @@ vtmmio_read_dev_config(device_t dev, bus_size_t offset,
|
||||
off = VIRTIO_MMIO_CONFIG + offset;
|
||||
|
||||
for (d = dst; length > 0; d += size, off += size, length -= size) {
|
||||
#ifdef ALLOW_WORD_ALIGNED_ACCESS
|
||||
if (length >= 4) {
|
||||
size = 4;
|
||||
*(uint32_t *)d = vtmmio_read_config_4(sc, off);
|
||||
} else if (length >= 2) {
|
||||
size = 2;
|
||||
*(uint16_t *)d = vtmmio_read_config_2(sc, off);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
size = 1;
|
||||
*d = vtmmio_read_config_1(sc, off);
|
||||
}
|
||||
@ -637,13 +661,16 @@ vtmmio_write_dev_config(device_t dev, bus_size_t offset,
|
||||
off = VIRTIO_MMIO_CONFIG + offset;
|
||||
|
||||
for (s = src; length > 0; s += size, off += size, length -= size) {
|
||||
#ifdef ALLOW_WORD_ALIGNED_ACCESS
|
||||
if (length >= 4) {
|
||||
size = 4;
|
||||
vtmmio_write_config_4(sc, off, *(uint32_t *)s);
|
||||
} else if (length >= 2) {
|
||||
size = 2;
|
||||
vtmmio_write_config_2(sc, off, *(uint16_t *)s);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
size = 1;
|
||||
vtmmio_write_config_1(sc, off, *s);
|
||||
}
|
||||
@ -711,7 +738,7 @@ vtmmio_reinit_virtqueue(struct vtmmio_softc *sc, int idx)
|
||||
KASSERT(vq != NULL, ("%s: vq %d not allocated", __func__, idx));
|
||||
|
||||
vtmmio_select_virtqueue(sc, idx);
|
||||
size = vtmmio_read_config_2(sc, VIRTIO_MMIO_QUEUE_NUM);
|
||||
size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
|
||||
|
||||
error = virtqueue_reinit(vq, size);
|
||||
if (error)
|
||||
@ -778,7 +805,7 @@ static void
|
||||
vtmmio_select_virtqueue(struct vtmmio_softc *sc, int idx)
|
||||
{
|
||||
|
||||
vtmmio_write_config_2(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -787,14 +814,27 @@ vtmmio_vq_intr(void *arg)
|
||||
struct vtmmio_virtqueue *vqx;
|
||||
struct vtmmio_softc *sc;
|
||||
struct virtqueue *vq;
|
||||
uint32_t status;
|
||||
int idx;
|
||||
|
||||
sc = arg;
|
||||
|
||||
status = vtmmio_read_config_4(sc, VIRTIO_MMIO_INTERRUPT_STATUS);
|
||||
vtmmio_write_config_4(sc, VIRTIO_MMIO_INTERRUPT_ACK, status);
|
||||
|
||||
/* The config changed */
|
||||
if (status & VIRTIO_MMIO_INT_CONFIG)
|
||||
if (sc->vtmmio_child_dev != NULL)
|
||||
VIRTIO_CONFIG_CHANGE(sc->vtmmio_child_dev);
|
||||
|
||||
/* Notify all virtqueues. */
|
||||
for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
|
||||
vqx = &sc->vtmmio_vqs[idx];
|
||||
vq = vqx->vtv_vq;
|
||||
virtqueue_intr(vq);
|
||||
};
|
||||
if (status & VIRTIO_MMIO_INT_VRING) {
|
||||
for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
|
||||
vqx = &sc->vtmmio_vqs[idx];
|
||||
if (vqx->vtv_no_intr == 0) {
|
||||
vq = vqx->vtv_vq;
|
||||
virtqueue_intr(vq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ INTERFACE virtio_mmio;
|
||||
|
||||
CODE {
|
||||
static int
|
||||
virtio_mmio_write(device_t dev, size_t offset)
|
||||
virtio_mmio_note(device_t dev, size_t offset, int val)
|
||||
{
|
||||
|
||||
return (1);
|
||||
@ -63,7 +63,8 @@ CODE {
|
||||
METHOD int note {
|
||||
device_t dev;
|
||||
size_t offset;
|
||||
} DEFAULT virtio_mmio_write;
|
||||
int val;
|
||||
} DEFAULT virtio_mmio_note;
|
||||
|
||||
#
|
||||
# Setup backend-specific interrupts.
|
||||
|
88
sys/dev/xen/pci/xen_acpi_pci.c
Normal file
88
sys/dev/xen/pci/xen_acpi_pci.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <contrib/dev/acpica/include/acpi.h>
|
||||
#include <contrib/dev/acpica/include/accommon.h>
|
||||
|
||||
#include <dev/acpica/acpivar.h>
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pci_private.h>
|
||||
|
||||
#include <xen/xen-os.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_pci.h>
|
||||
|
||||
#include "pcib_if.h"
|
||||
#include "pci_if.h"
|
||||
|
||||
static int
|
||||
xen_acpi_pci_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!xen_pv_domain())
|
||||
return (ENXIO);
|
||||
if (acpi_get_handle(dev) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Xen ACPI PCI bus");
|
||||
|
||||
return (BUS_PROBE_SPECIFIC);
|
||||
}
|
||||
|
||||
static device_method_t xen_acpi_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, xen_acpi_pci_probe),
|
||||
|
||||
/* PCI interface overwrites */
|
||||
DEVMETHOD(pci_enable_msi, xen_pci_enable_msi_method),
|
||||
DEVMETHOD(pci_disable_msi, xen_pci_disable_msi_method),
|
||||
DEVMETHOD(pci_child_added, xen_pci_child_added_method),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
DECLARE_CLASS(acpi_pci_driver);
|
||||
DEFINE_CLASS_1(pci, xen_acpi_pci_driver, xen_acpi_pci_methods,
|
||||
sizeof(struct pci_softc), acpi_pci_driver);
|
||||
DRIVER_MODULE(xen_acpi_pci, pcib, xen_acpi_pci_driver, pci_devclass, 0, 0);
|
||||
MODULE_DEPEND(xen_acpi_pci, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(xen_acpi_pci, acpi, 1, 1, 1);
|
||||
MODULE_VERSION(xen_acpi_pci, 1);
|
80
sys/dev/xen/pci/xen_pci.c
Normal file
80
sys/dev/xen/pci/xen_pci.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pci_private.h>
|
||||
|
||||
#include <xen/xen-os.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_pci.h>
|
||||
|
||||
#include "pcib_if.h"
|
||||
#include "pci_if.h"
|
||||
|
||||
static int
|
||||
xen_pci_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!xen_pv_domain())
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Xen PCI bus");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static device_method_t xen_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, xen_pci_probe),
|
||||
|
||||
/* PCI interface overwrites */
|
||||
DEVMETHOD(pci_enable_msi, xen_pci_enable_msi_method),
|
||||
DEVMETHOD(pci_disable_msi, xen_pci_disable_msi_method),
|
||||
DEVMETHOD(pci_child_added, xen_pci_child_added_method),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
DECLARE_CLASS(pci_driver);
|
||||
DEFINE_CLASS_1(pci, xen_pci_driver, xen_pci_methods, sizeof(struct pci_softc),
|
||||
pci_driver);
|
||||
DRIVER_MODULE(xen_pci, pcib, xen_pci_driver, pci_devclass, 0, 0);
|
||||
MODULE_DEPEND(xen_pci, pci, 1, 1, 1);
|
||||
MODULE_VERSION(xen_pci, 1);
|
@ -224,14 +224,18 @@ ext2_truncate(struct vnode *vp, off_t length, int flags, struct ucred *cred,
|
||||
* will be returned to the free list. lastiblock values are also
|
||||
* normalized to -1 for calls to ext2_indirtrunc below.
|
||||
*/
|
||||
bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof(oldblks));
|
||||
for (level = TRIPLE; level >= SINGLE; level--)
|
||||
for (level = TRIPLE; level >= SINGLE; level--) {
|
||||
oldblks[NDADDR + level] = oip->i_ib[level];
|
||||
if (lastiblock[level] < 0) {
|
||||
oip->i_ib[level] = 0;
|
||||
lastiblock[level] = -1;
|
||||
}
|
||||
for (i = NDADDR - 1; i > lastblock; i--)
|
||||
oip->i_db[i] = 0;
|
||||
}
|
||||
for (i = 0; i < NDADDR; i++) {
|
||||
oldblks[i] = oip->i_db[i];
|
||||
if (i > lastblock)
|
||||
oip->i_db[i] = 0;
|
||||
}
|
||||
oip->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||
allerror = ext2_update(ovp, !DOINGASYNC(ovp));
|
||||
|
||||
@ -241,8 +245,14 @@ ext2_truncate(struct vnode *vp, off_t length, int flags, struct ucred *cred,
|
||||
* Note that we save the new block configuration so we can check it
|
||||
* when we are done.
|
||||
*/
|
||||
bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof(newblks));
|
||||
bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof(oldblks));
|
||||
for (i = 0; i < NDADDR; i++) {
|
||||
newblks[i] = oip->i_db[i];
|
||||
oip->i_db[i] = oldblks[i];
|
||||
}
|
||||
for (i = 0; i < NIADDR; i++) {
|
||||
newblks[NDADDR + i] = oip->i_ib[i];
|
||||
oip->i_ib[i] = oldblks[NDADDR + i];
|
||||
}
|
||||
oip->i_size = osize;
|
||||
error = vtruncbuf(ovp, cred, length, (int)fs->e2fs_bsize);
|
||||
if (error && (allerror == 0))
|
||||
|
@ -797,11 +797,15 @@ msdosfs_unmount(struct mount *mp, int mntflags)
|
||||
int error, flags;
|
||||
|
||||
flags = 0;
|
||||
if (mntflags & MNT_FORCE)
|
||||
error = msdosfs_sync(mp, MNT_WAIT);
|
||||
if ((mntflags & MNT_FORCE) != 0) {
|
||||
flags |= FORCECLOSE;
|
||||
} else if (error != 0) {
|
||||
return (error);
|
||||
}
|
||||
error = vflush(mp, 0, flags, curthread);
|
||||
if (error && error != ENXIO)
|
||||
return error;
|
||||
if (error != 0 && error != ENXIO)
|
||||
return (error);
|
||||
pmp = VFSTOMSDOSFS(mp);
|
||||
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) {
|
||||
error = markvoldirty(pmp, 0);
|
||||
|
@ -182,13 +182,14 @@ exit1(struct thread *td, int rv)
|
||||
* MUST abort all other threads before proceeding past here.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
/*
|
||||
* First check if some other thread or external request got
|
||||
* here before us. If so, act appropriately: exit or suspend.
|
||||
* We must ensure that stop requests are handled before we set
|
||||
* P_WEXIT.
|
||||
*/
|
||||
thread_suspend_check(0);
|
||||
while (p->p_flag & P_HADTHREADS) {
|
||||
/*
|
||||
* First check if some other thread got here before us.
|
||||
* If so, act appropriately: exit or suspend.
|
||||
*/
|
||||
thread_suspend_check(0);
|
||||
|
||||
/*
|
||||
* Kill off the other threads. This requires
|
||||
* some co-operation from other parts of the kernel
|
||||
@ -207,12 +208,18 @@ exit1(struct thread *td, int rv)
|
||||
* either be suspended there or exit.
|
||||
*/
|
||||
if (!thread_single(SINGLE_EXIT))
|
||||
/*
|
||||
* All other activity in this process is now
|
||||
* stopped. Threading support has been turned
|
||||
* off.
|
||||
*/
|
||||
break;
|
||||
|
||||
/*
|
||||
* All other activity in this process is now stopped.
|
||||
* Threading support has been turned off.
|
||||
* Recheck for new stop or suspend requests which
|
||||
* might appear while process lock was dropped in
|
||||
* thread_single().
|
||||
*/
|
||||
thread_suspend_check(0);
|
||||
}
|
||||
KASSERT(p->p_numthreads == 1,
|
||||
("exit1: proc %p exiting with %d threads", p, p->p_numthreads));
|
||||
|
@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
|
||||
SDT_PROVIDER_DECLARE(proc);
|
||||
SDT_PROBE_DEFINE(proc, , , lwp__exit);
|
||||
|
||||
|
||||
/*
|
||||
* thread related storage.
|
||||
*/
|
||||
@ -584,6 +583,46 @@ calc_remaining(struct proc *p, int mode)
|
||||
return (remaining);
|
||||
}
|
||||
|
||||
static int
|
||||
remain_for_mode(int mode)
|
||||
{
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
weed_inhib(int mode, struct thread *td2, struct proc *p)
|
||||
{
|
||||
int wakeup_swapper;
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
PROC_SLOCK_ASSERT(p, MA_OWNED);
|
||||
THREAD_LOCK_ASSERT(td2, MA_OWNED);
|
||||
|
||||
wakeup_swapper = 0;
|
||||
switch (mode) {
|
||||
case SINGLE_EXIT:
|
||||
if (TD_IS_SUSPENDED(td2))
|
||||
wakeup_swapper |= thread_unsuspend_one(td2);
|
||||
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0)
|
||||
wakeup_swapper |= sleepq_abort(td2, EINTR);
|
||||
break;
|
||||
case SINGLE_BOUNDARY:
|
||||
if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0)
|
||||
wakeup_swapper |= thread_unsuspend_one(td2);
|
||||
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0)
|
||||
wakeup_swapper |= sleepq_abort(td2, ERESTART);
|
||||
break;
|
||||
case SINGLE_NO_EXIT:
|
||||
if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0)
|
||||
wakeup_swapper |= thread_unsuspend_one(td2);
|
||||
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0)
|
||||
wakeup_swapper |= sleepq_abort(td2, ERESTART);
|
||||
break;
|
||||
}
|
||||
return (wakeup_swapper);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enforce single-threading.
|
||||
*
|
||||
@ -631,7 +670,7 @@ thread_single(int mode)
|
||||
PROC_SLOCK(p);
|
||||
p->p_singlethread = td;
|
||||
remaining = calc_remaining(p, mode);
|
||||
while (remaining != 1) {
|
||||
while (remaining != remain_for_mode(mode)) {
|
||||
if (P_SHOULDSTOP(p) != P_STOPPED_SINGLE)
|
||||
goto stopme;
|
||||
wakeup_swapper = 0;
|
||||
@ -640,41 +679,8 @@ thread_single(int mode)
|
||||
continue;
|
||||
thread_lock(td2);
|
||||
td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
|
||||
if (TD_IS_INHIBITED(td2)) {
|
||||
switch (mode) {
|
||||
case SINGLE_EXIT:
|
||||
if (TD_IS_SUSPENDED(td2))
|
||||
wakeup_swapper |=
|
||||
thread_unsuspend_one(td2);
|
||||
if (TD_ON_SLEEPQ(td2) &&
|
||||
(td2->td_flags & TDF_SINTR))
|
||||
wakeup_swapper |=
|
||||
sleepq_abort(td2, EINTR);
|
||||
break;
|
||||
case SINGLE_BOUNDARY:
|
||||
if (TD_IS_SUSPENDED(td2) &&
|
||||
!(td2->td_flags & TDF_BOUNDARY))
|
||||
wakeup_swapper |=
|
||||
thread_unsuspend_one(td2);
|
||||
if (TD_ON_SLEEPQ(td2) &&
|
||||
(td2->td_flags & TDF_SINTR))
|
||||
wakeup_swapper |=
|
||||
sleepq_abort(td2, ERESTART);
|
||||
break;
|
||||
case SINGLE_NO_EXIT:
|
||||
if (TD_IS_SUSPENDED(td2) &&
|
||||
!(td2->td_flags & TDF_BOUNDARY))
|
||||
wakeup_swapper |=
|
||||
thread_unsuspend_one(td2);
|
||||
if (TD_ON_SLEEPQ(td2) &&
|
||||
(td2->td_flags & TDF_SINTR))
|
||||
wakeup_swapper |=
|
||||
sleepq_abort(td2, ERESTART);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (TD_IS_INHIBITED(td2))
|
||||
wakeup_swapper |= weed_inhib(mode, td2, p);
|
||||
#ifdef SMP
|
||||
else if (TD_IS_RUNNING(td2) && td != td2) {
|
||||
forward_signal(td2);
|
||||
@ -689,7 +695,7 @@ thread_single(int mode)
|
||||
/*
|
||||
* Maybe we suspended some threads.. was it enough?
|
||||
*/
|
||||
if (remaining == 1)
|
||||
if (remaining == remain_for_mode(mode))
|
||||
break;
|
||||
|
||||
stopme:
|
||||
@ -725,6 +731,19 @@ thread_single(int mode)
|
||||
return (0);
|
||||
}
|
||||
|
||||
bool
|
||||
thread_suspend_check_needed(void)
|
||||
{
|
||||
struct proc *p;
|
||||
struct thread *td;
|
||||
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
return (P_SHOULDSTOP(p) || ((p->p_flag & P_TRACED) != 0 &&
|
||||
(td->td_dbgflags & TDB_SUSPEND) != 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Called in from locations that can safely check to see
|
||||
* whether we have to suspend or at least throttle for a
|
||||
@ -769,8 +788,7 @@ thread_suspend_check(int return_instead)
|
||||
p = td->td_proc;
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
while (P_SHOULDSTOP(p) ||
|
||||
((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_SUSPEND))) {
|
||||
while (thread_suspend_check_needed()) {
|
||||
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
|
||||
KASSERT(p->p_singlethread != NULL,
|
||||
("singlethread not set"));
|
||||
@ -956,8 +974,7 @@ thread_single_end(void)
|
||||
struct proc *p;
|
||||
int wakeup_swapper;
|
||||
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
p = curproc;
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT | P_SINGLE_BOUNDARY);
|
||||
PROC_SLOCK(p);
|
||||
@ -969,7 +986,8 @@ thread_single_end(void)
|
||||
* on the process. The single threader must be allowed
|
||||
* to continue however as this is a bad place to stop.
|
||||
*/
|
||||
if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) {
|
||||
if (p->p_numthreads != remain_for_mode(SINGLE_EXIT) &&
|
||||
!P_SHOULDSTOP(p)) {
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
thread_lock(td);
|
||||
if (TD_IS_SUSPENDED(td)) {
|
||||
|
@ -226,9 +226,20 @@ syscallret(struct thread *td, int error, struct syscall_args *sa __unused)
|
||||
*/
|
||||
td->td_pflags &= ~TDP_RFPPWAIT;
|
||||
p2 = td->td_rfppwait_p;
|
||||
again:
|
||||
PROC_LOCK(p2);
|
||||
while (p2->p_flag & P_PPWAIT)
|
||||
cv_wait(&p2->p_pwait, &p2->p_mtx);
|
||||
while (p2->p_flag & P_PPWAIT) {
|
||||
PROC_LOCK(p);
|
||||
if (thread_suspend_check_needed()) {
|
||||
PROC_UNLOCK(p2);
|
||||
thread_suspend_check(0);
|
||||
PROC_UNLOCK(p);
|
||||
goto again;
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
cv_timedwait(&p2->p_pwait, &p2->p_mtx, hz);
|
||||
}
|
||||
PROC_UNLOCK(p2);
|
||||
}
|
||||
}
|
||||
|
@ -1883,15 +1883,18 @@ bqrelse(struct buf *bp)
|
||||
static void
|
||||
vfs_vmio_release(struct buf *bp)
|
||||
{
|
||||
int i;
|
||||
vm_object_t obj;
|
||||
vm_page_t m;
|
||||
int i;
|
||||
|
||||
if ((bp->b_flags & B_UNMAPPED) == 0) {
|
||||
BUF_CHECK_MAPPED(bp);
|
||||
pmap_qremove(trunc_page((vm_offset_t)bp->b_data), bp->b_npages);
|
||||
} else
|
||||
BUF_CHECK_UNMAPPED(bp);
|
||||
VM_OBJECT_WLOCK(bp->b_bufobj->bo_object);
|
||||
obj = bp->b_bufobj->bo_object;
|
||||
if (obj != NULL)
|
||||
VM_OBJECT_WLOCK(obj);
|
||||
for (i = 0; i < bp->b_npages; i++) {
|
||||
m = bp->b_pages[i];
|
||||
bp->b_pages[i] = NULL;
|
||||
@ -1916,7 +1919,8 @@ vfs_vmio_release(struct buf *bp)
|
||||
vm_page_try_to_cache(m);
|
||||
vm_page_unlock(m);
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(bp->b_bufobj->bo_object);
|
||||
if (obj != NULL)
|
||||
VM_OBJECT_WUNLOCK(obj);
|
||||
|
||||
if (bp->b_bufsize) {
|
||||
bufspacewakeup();
|
||||
|
@ -1305,8 +1305,8 @@ dounmount(mp, flags, td)
|
||||
}
|
||||
vput(fsrootvp);
|
||||
}
|
||||
if (((mp->mnt_flag & MNT_RDONLY) ||
|
||||
(error = VFS_SYNC(mp, MNT_WAIT)) == 0) || (flags & MNT_FORCE) != 0)
|
||||
if ((mp->mnt_flag & MNT_RDONLY) != 0 || (flags & MNT_FORCE) != 0 ||
|
||||
(error = VFS_SYNC(mp, MNT_WAIT)) == 0)
|
||||
error = VFS_UNMOUNT(mp, flags);
|
||||
vn_finished_write(mp);
|
||||
/*
|
||||
|
@ -1773,6 +1773,8 @@ sync_vnode(struct synclist *slp, struct bufobj **bo, struct thread *td)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int first_printf = 1;
|
||||
|
||||
/*
|
||||
* System filesystem synchronizer daemon.
|
||||
*/
|
||||
@ -1786,12 +1788,10 @@ sched_sync(void)
|
||||
int last_work_seen;
|
||||
int net_worklist_len;
|
||||
int syncer_final_iter;
|
||||
int first_printf;
|
||||
int error;
|
||||
|
||||
last_work_seen = 0;
|
||||
syncer_final_iter = 0;
|
||||
first_printf = 1;
|
||||
syncer_state = SYNCER_RUNNING;
|
||||
starttime = time_uptime;
|
||||
td->td_pflags |= TDP_NORUNNINGBUF;
|
||||
@ -1955,6 +1955,25 @@ syncer_shutdown(void *arg, int howto)
|
||||
kproc_shutdown(arg, howto);
|
||||
}
|
||||
|
||||
void
|
||||
syncer_suspend(void)
|
||||
{
|
||||
|
||||
syncer_shutdown(updateproc, 0);
|
||||
}
|
||||
|
||||
void
|
||||
syncer_resume(void)
|
||||
{
|
||||
|
||||
mtx_lock(&sync_mtx);
|
||||
first_printf = 1;
|
||||
syncer_state = SYNCER_RUNNING;
|
||||
mtx_unlock(&sync_mtx);
|
||||
cv_broadcast(&sync_wakeup);
|
||||
kproc_resume(updateproc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reassign a buffer from one vnode to another.
|
||||
* Used to assign file specific control information
|
||||
|
@ -153,6 +153,8 @@ nd6_init(void)
|
||||
callout_init(&V_nd6_slowtimo_ch, 0);
|
||||
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
|
||||
nd6_slowtimo, curvnet);
|
||||
|
||||
nd6_dad_init();
|
||||
}
|
||||
|
||||
#ifdef VIMAGE
|
||||
|
@ -428,6 +428,7 @@ void nd6_ns_input(struct mbuf *, int, int);
|
||||
void nd6_ns_output(struct ifnet *, const struct in6_addr *,
|
||||
const struct in6_addr *, struct llentry *, int);
|
||||
caddr_t nd6_ifptomac(struct ifnet *);
|
||||
void nd6_dad_init(void);
|
||||
void nd6_dad_start(struct ifaddr *, int);
|
||||
void nd6_dad_stop(struct ifaddr *);
|
||||
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/refcount.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@ -81,6 +82,7 @@ struct dadq;
|
||||
static struct dadq *nd6_dad_find(struct ifaddr *);
|
||||
static void nd6_dad_add(struct dadq *dp);
|
||||
static void nd6_dad_del(struct dadq *dp);
|
||||
static void nd6_dad_rele(struct dadq *);
|
||||
static void nd6_dad_starttimer(struct dadq *, int);
|
||||
static void nd6_dad_stoptimer(struct dadq *);
|
||||
static void nd6_dad_timer(struct dadq *);
|
||||
@ -1167,6 +1169,7 @@ struct dadq {
|
||||
int dad_na_icount;
|
||||
struct callout dad_timer_ch;
|
||||
struct vnet *dad_vnet;
|
||||
u_int dad_refcnt;
|
||||
};
|
||||
|
||||
static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
|
||||
@ -1174,9 +1177,6 @@ static VNET_DEFINE(struct rwlock, dad_rwlock);
|
||||
#define V_dadq VNET(dadq)
|
||||
#define V_dad_rwlock VNET(dad_rwlock)
|
||||
|
||||
#define DADQ_LOCK_INIT() rw_init(&V_dad_rwlock, "nd6 DAD queue")
|
||||
#define DADQ_LOCK_DESTROY() rw_destroy(&V_dad_rwlock)
|
||||
#define DADQ_LOCK_INITIALIZED() rw_initialized(&V_dad_rwlock)
|
||||
#define DADQ_RLOCK() rw_rlock(&V_dad_rwlock)
|
||||
#define DADQ_RUNLOCK() rw_runlock(&V_dad_rwlock)
|
||||
#define DADQ_WLOCK() rw_wlock(&V_dad_rwlock)
|
||||
@ -1186,9 +1186,8 @@ static void
|
||||
nd6_dad_add(struct dadq *dp)
|
||||
{
|
||||
|
||||
ifa_ref(dp->dad_ifa); /* just for safety */
|
||||
DADQ_WLOCK();
|
||||
TAILQ_INSERT_TAIL(&V_dadq, (struct dadq *)dp, dad_list);
|
||||
TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list);
|
||||
DADQ_WUNLOCK();
|
||||
}
|
||||
|
||||
@ -1196,10 +1195,10 @@ static void
|
||||
nd6_dad_del(struct dadq *dp)
|
||||
{
|
||||
|
||||
ifa_free(dp->dad_ifa);
|
||||
DADQ_WLOCK();
|
||||
TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
|
||||
TAILQ_REMOVE(&V_dadq, dp, dad_list);
|
||||
DADQ_WUNLOCK();
|
||||
nd6_dad_rele(dp);
|
||||
}
|
||||
|
||||
static struct dadq *
|
||||
@ -1209,8 +1208,10 @@ nd6_dad_find(struct ifaddr *ifa)
|
||||
|
||||
DADQ_RLOCK();
|
||||
TAILQ_FOREACH(dp, &V_dadq, dad_list)
|
||||
if (dp->dad_ifa == ifa)
|
||||
if (dp->dad_ifa == ifa) {
|
||||
refcount_acquire(&dp->dad_refcnt);
|
||||
break;
|
||||
}
|
||||
DADQ_RUNLOCK();
|
||||
|
||||
return (dp);
|
||||
@ -1228,7 +1229,25 @@ static void
|
||||
nd6_dad_stoptimer(struct dadq *dp)
|
||||
{
|
||||
|
||||
callout_stop(&dp->dad_timer_ch);
|
||||
callout_drain(&dp->dad_timer_ch);
|
||||
}
|
||||
|
||||
static void
|
||||
nd6_dad_rele(struct dadq *dp)
|
||||
{
|
||||
|
||||
if (refcount_release(&dp->dad_refcnt)) {
|
||||
ifa_free(dp->dad_ifa);
|
||||
free(dp, M_IP6NDP);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nd6_dad_init(void)
|
||||
{
|
||||
|
||||
rw_init(&V_dad_rwlock, "nd6 DAD queue");
|
||||
TAILQ_INIT(&V_dadq);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1241,11 +1260,6 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
struct dadq *dp;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (DADQ_LOCK_INITIALIZED() == 0) {
|
||||
DADQ_LOCK_INIT();
|
||||
TAILQ_INIT(&V_dadq);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we don't need DAD, don't do it.
|
||||
* There are several cases:
|
||||
@ -1275,12 +1289,13 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
}
|
||||
if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)
|
||||
return;
|
||||
if (nd6_dad_find(ifa) != NULL) {
|
||||
if ((dp = nd6_dad_find(ifa)) != NULL) {
|
||||
/* DAD already in progress */
|
||||
nd6_dad_rele(dp);
|
||||
return;
|
||||
}
|
||||
|
||||
dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT);
|
||||
dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
|
||||
if (dp == NULL) {
|
||||
log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
|
||||
"%s(%s)\n",
|
||||
@ -1288,7 +1303,6 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
|
||||
return;
|
||||
}
|
||||
bzero(dp, sizeof(*dp));
|
||||
callout_init(&dp->dad_timer_ch, 0);
|
||||
#ifdef VIMAGE
|
||||
dp->dad_vnet = curvnet;
|
||||
@ -1303,9 +1317,11 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
|
||||
* (re)initialization.
|
||||
*/
|
||||
dp->dad_ifa = ifa;
|
||||
ifa_ref(dp->dad_ifa);
|
||||
dp->dad_count = V_ip6_dad_count;
|
||||
dp->dad_ns_icount = dp->dad_na_icount = 0;
|
||||
dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
|
||||
refcount_init(&dp->dad_refcnt, 1);
|
||||
nd6_dad_add(dp);
|
||||
if (delay == 0) {
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
@ -1324,8 +1340,6 @@ nd6_dad_stop(struct ifaddr *ifa)
|
||||
{
|
||||
struct dadq *dp;
|
||||
|
||||
if (DADQ_LOCK_INITIALIZED() == 0)
|
||||
return;
|
||||
dp = nd6_dad_find(ifa);
|
||||
if (!dp) {
|
||||
/* DAD wasn't started yet */
|
||||
@ -1334,8 +1348,16 @@ nd6_dad_stop(struct ifaddr *ifa)
|
||||
|
||||
nd6_dad_stoptimer(dp);
|
||||
|
||||
/*
|
||||
* The DAD queue entry may have been removed by nd6_dad_timer() while
|
||||
* we were waiting for it to stop, so re-do the lookup.
|
||||
*/
|
||||
nd6_dad_rele(dp);
|
||||
if (nd6_dad_find(ifa) == NULL)
|
||||
return;
|
||||
|
||||
nd6_dad_del(dp);
|
||||
free(dp, M_IP6NDP);
|
||||
nd6_dad_rele(dp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1350,42 +1372,34 @@ nd6_dad_timer(struct dadq *dp)
|
||||
/* Sanity check */
|
||||
if (ia == NULL) {
|
||||
log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
|
||||
goto done;
|
||||
goto err;
|
||||
}
|
||||
if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
|
||||
/* Do not need DAD for ifdisabled interface. */
|
||||
TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
|
||||
log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of "
|
||||
"ND6_IFF_IFDISABLED.\n", ifp->if_xname);
|
||||
free(dp, M_IP6NDP);
|
||||
dp = NULL;
|
||||
ifa_free(ifa);
|
||||
goto done;
|
||||
goto err;
|
||||
}
|
||||
if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
|
||||
log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
|
||||
"%s(%s)\n",
|
||||
ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
|
||||
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
|
||||
goto done;
|
||||
goto err;
|
||||
}
|
||||
if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
|
||||
log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
|
||||
"%s(%s)\n",
|
||||
ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
|
||||
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
|
||||
goto done;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* timeouted with IFF_{RUNNING,UP} check */
|
||||
if (dp->dad_ns_tcount > V_dad_maxtry) {
|
||||
nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
|
||||
if_name(ifa->ifa_ifp)));
|
||||
|
||||
nd6_dad_del(dp);
|
||||
free(dp, M_IP6NDP);
|
||||
dp = NULL;
|
||||
goto done;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Need more checks? */
|
||||
@ -1396,33 +1410,16 @@ nd6_dad_timer(struct dadq *dp)
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
(long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
goto done;
|
||||
} else {
|
||||
/*
|
||||
* We have transmitted sufficient number of DAD packets.
|
||||
* See what we've got.
|
||||
*/
|
||||
int duplicate;
|
||||
|
||||
duplicate = 0;
|
||||
|
||||
if (dp->dad_na_icount) {
|
||||
/*
|
||||
* the check is in nd6_dad_na_input(),
|
||||
* but just in case
|
||||
*/
|
||||
duplicate++;
|
||||
}
|
||||
|
||||
if (dp->dad_ns_icount) {
|
||||
/* We've seen NS, means DAD has failed. */
|
||||
duplicate++;
|
||||
}
|
||||
|
||||
if (duplicate) {
|
||||
/* (*dp) will be freed in nd6_dad_duplicated() */
|
||||
if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0)
|
||||
/* We've seen NS or NA, means DAD has failed. */
|
||||
nd6_dad_duplicated(ifa, dp);
|
||||
dp = NULL;
|
||||
} else {
|
||||
else {
|
||||
/*
|
||||
* We are done with DAD. No NA came, no NS came.
|
||||
* No duplicate address found. Check IFDISABLED flag
|
||||
@ -1436,18 +1433,15 @@ nd6_dad_timer(struct dadq *dp)
|
||||
"%s: DAD complete for %s - no duplicates found\n",
|
||||
if_name(ifa->ifa_ifp),
|
||||
ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
|
||||
|
||||
nd6_dad_del(dp);
|
||||
free(dp, M_IP6NDP);
|
||||
dp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
nd6_dad_del(dp);
|
||||
done:
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
|
||||
{
|
||||
struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
|
||||
@ -1462,9 +1456,6 @@ nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
|
||||
ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
|
||||
ia->ia6_flags |= IN6_IFF_DUPLICATED;
|
||||
|
||||
/* We are done with DAD, with duplicate address found. (failure) */
|
||||
nd6_dad_stoptimer(dp);
|
||||
|
||||
ifp = ifa->ifa_ifp;
|
||||
log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
|
||||
if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr));
|
||||
@ -1505,9 +1496,6 @@ nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nd6_dad_del(dp);
|
||||
free(dp, M_IP6NDP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1535,7 +1523,6 @@ nd6_dad_ns_input(struct ifaddr *ifa)
|
||||
struct ifnet *ifp;
|
||||
const struct in6_addr *taddr6;
|
||||
struct dadq *dp;
|
||||
int duplicate;
|
||||
|
||||
if (ifa == NULL)
|
||||
panic("ifa == NULL in nd6_dad_ns_input");
|
||||
@ -1543,8 +1530,9 @@ nd6_dad_ns_input(struct ifaddr *ifa)
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
ifp = ifa->ifa_ifp;
|
||||
taddr6 = &ia->ia_addr.sin6_addr;
|
||||
duplicate = 0;
|
||||
dp = nd6_dad_find(ifa);
|
||||
if (dp == NULL)
|
||||
return;
|
||||
|
||||
/* Quickhack - completely ignore DAD NS packets */
|
||||
if (V_dad_ignore_ns) {
|
||||
@ -1556,26 +1544,10 @@ nd6_dad_ns_input(struct ifaddr *ifa)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if I'm yet to start DAD, someone else started using this address
|
||||
* first. I have a duplicate and you win.
|
||||
*/
|
||||
if (dp == NULL || dp->dad_ns_ocount == 0)
|
||||
duplicate++;
|
||||
|
||||
/* XXX more checks for loopback situation - see nd6_dad_timer too */
|
||||
|
||||
if (duplicate) {
|
||||
nd6_dad_duplicated(ifa, dp);
|
||||
dp = NULL; /* will be freed in nd6_dad_duplicated() */
|
||||
} else {
|
||||
/*
|
||||
* not sure if I got a duplicate.
|
||||
* increment ns count and see what happens.
|
||||
*/
|
||||
if (dp)
|
||||
dp->dad_ns_icount++;
|
||||
}
|
||||
dp->dad_ns_icount++;
|
||||
nd6_dad_rele(dp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1587,9 +1559,8 @@ nd6_dad_na_input(struct ifaddr *ifa)
|
||||
panic("ifa == NULL in nd6_dad_na_input");
|
||||
|
||||
dp = nd6_dad_find(ifa);
|
||||
if (dp)
|
||||
if (dp != NULL) {
|
||||
dp->dad_na_icount++;
|
||||
|
||||
/* remove the address. */
|
||||
nd6_dad_duplicated(ifa, dp);
|
||||
nd6_dad_rele(dp);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
@ -53,6 +54,7 @@
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
|
@ -49,9 +49,9 @@
|
||||
#define EXPORT_SYMBOL_GPL(name)
|
||||
|
||||
/* OFED pre-module initialization */
|
||||
#define SI_SUB_OFED_PREINIT (SI_SUB_KTHREAD_INIT - 2)
|
||||
#define SI_SUB_OFED_PREINIT (SI_SUB_ROOT_CONF - 2)
|
||||
/* OFED default module initialization */
|
||||
#define SI_SUB_OFED_MODINIT (SI_SUB_KTHREAD_INIT - 1)
|
||||
#define SI_SUB_OFED_MODINIT (SI_SUB_ROOT_CONF - 1)
|
||||
|
||||
#include <sys/linker.h>
|
||||
|
||||
|
@ -45,8 +45,10 @@
|
||||
#ifdef INET
|
||||
static inline void inet_get_local_port_range(int *low, int *high)
|
||||
{
|
||||
CURVNET_SET_QUIET(TD_TO_VNET(curthread));
|
||||
*low = V_ipport_firstauto;
|
||||
*high = V_ipport_lastauto;
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -1101,6 +1101,7 @@ svc_run_internal(SVCGROUP *grp, bool_t ismaster)
|
||||
SVCXPRT *xprt;
|
||||
enum xprt_stat stat;
|
||||
struct svc_req *rqstp;
|
||||
struct proc *p;
|
||||
size_t sz;
|
||||
int error;
|
||||
|
||||
@ -1183,11 +1184,22 @@ svc_run_internal(SVCGROUP *grp, bool_t ismaster)
|
||||
> grp->sg_minthreads)
|
||||
&& !st->st_xprt)
|
||||
break;
|
||||
} else if (error) {
|
||||
} else if (error != 0) {
|
||||
KASSERT(error == EINTR || error == ERESTART,
|
||||
("non-signal error %d", error));
|
||||
mtx_unlock(&grp->sg_lock);
|
||||
svc_exit(pool);
|
||||
mtx_lock(&grp->sg_lock);
|
||||
break;
|
||||
p = curproc;
|
||||
PROC_LOCK(p);
|
||||
if (P_SHOULDSTOP(p)) {
|
||||
thread_suspend_check(0);
|
||||
PROC_UNLOCK(p);
|
||||
mtx_lock(&grp->sg_lock);
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
svc_exit(pool);
|
||||
mtx_lock(&grp->sg_lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -917,6 +917,9 @@ vfs_uninit_t vfs_stduninit;
|
||||
vfs_extattrctl_t vfs_stdextattrctl;
|
||||
vfs_sysctl_t vfs_stdsysctl;
|
||||
|
||||
void syncer_suspend(void);
|
||||
void syncer_resume(void);
|
||||
|
||||
#else /* !_KERNEL */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
@ -58,7 +58,7 @@
|
||||
* in the range 5 to 9.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1100048 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 1100049 /* Master, propagated to newvers */
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
@ -970,6 +970,7 @@ void childproc_stopped(struct proc *child, int reason);
|
||||
void childproc_continued(struct proc *child);
|
||||
void childproc_exited(struct proc *child);
|
||||
int thread_suspend_check(int how);
|
||||
bool thread_suspend_check_needed(void);
|
||||
void thread_suspend_switch(struct thread *);
|
||||
void thread_suspend_one(struct thread *td);
|
||||
void thread_unlink(struct thread *td);
|
||||
|
@ -91,6 +91,15 @@ madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
|
||||
|
||||
madt_parse_interrupt_values(intr, &trig, &pol);
|
||||
|
||||
/* Remap the IRQ if it is mapped to a different interrupt vector. */
|
||||
if (intr->SourceIrq != intr->GlobalIrq && intr->GlobalIrq > 15 &&
|
||||
intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
|
||||
/*
|
||||
* If the SCI is remapped to a non-ISA global interrupt,
|
||||
* then override the vector we use to setup.
|
||||
*/
|
||||
acpi_OverrideInterruptLevel(intr->GlobalIrq);
|
||||
|
||||
/* Register the IRQ with the polarity and trigger mode found. */
|
||||
xen_register_pirq(intr->GlobalIrq, trig, pol);
|
||||
}
|
||||
|
@ -31,8 +31,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
@ -41,52 +39,12 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <xen/xen-os.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_pci.h>
|
||||
|
||||
#include "pcib_if.h"
|
||||
#include "pci_if.h"
|
||||
|
||||
static int xen_pci_probe(device_t dev);
|
||||
|
||||
static void xen_pci_enable_msi_method(device_t dev, device_t child,
|
||||
uint64_t address, uint16_t data);
|
||||
static void xen_pci_disable_msi_method(device_t dev, device_t child);
|
||||
static void xen_pci_child_added_method(device_t dev, device_t child);
|
||||
|
||||
static device_method_t xen_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, xen_pci_probe),
|
||||
|
||||
/* PCI interface overwrites */
|
||||
DEVMETHOD(pci_enable_msi, xen_pci_enable_msi_method),
|
||||
DEVMETHOD(pci_disable_msi, xen_pci_disable_msi_method),
|
||||
DEVMETHOD(pci_child_added, xen_pci_child_added_method),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static devclass_t pci_devclass;
|
||||
|
||||
DECLARE_CLASS(acpi_pci_driver);
|
||||
DEFINE_CLASS_1(pci, xen_pci_driver, xen_pci_methods, sizeof(struct pci_softc),
|
||||
acpi_pci_driver);
|
||||
DRIVER_MODULE(xen_pci, pcib, xen_pci_driver, pci_devclass, 0, 0);
|
||||
MODULE_DEPEND(xen_pci, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(xen_pci, acpi, 1, 1, 1);
|
||||
MODULE_VERSION(xen_pci, 1);
|
||||
|
||||
static int
|
||||
xen_pci_probe(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "Xen PCI bus");
|
||||
|
||||
if (!xen_pv_domain())
|
||||
return (ENXIO);
|
||||
|
||||
return (BUS_PROBE_SPECIFIC);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
xen_pci_enable_msi_method(device_t dev, device_t child, uint64_t address,
|
||||
uint16_t data)
|
||||
{
|
||||
@ -99,7 +57,7 @@ xen_pci_enable_msi_method(device_t dev, device_t child, uint64_t address,
|
||||
msi->msi_ctrl, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
xen_pci_disable_msi_method(device_t dev, device_t child)
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(child);
|
||||
@ -110,7 +68,7 @@ xen_pci_disable_msi_method(device_t dev, device_t child)
|
||||
msi->msi_ctrl, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
xen_pci_child_added_method(device_t dev, device_t child)
|
||||
{
|
||||
struct pci_devinfo *dinfo;
|
37
sys/xen/xen_pci.h
Normal file
37
sys/xen/xen_pci.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PCI_H__
|
||||
#define __XEN_PCI_H__
|
||||
|
||||
void xen_pci_enable_msi_method(device_t dev, device_t child, uint64_t address,
|
||||
uint16_t data);
|
||||
void xen_pci_disable_msi_method(device_t dev, device_t child);
|
||||
void xen_pci_child_added_method(device_t dev, device_t child);
|
||||
|
||||
#endif /* !__XEN_PCI_H__ */
|
@ -55,7 +55,7 @@ CRUNCH_SRCDIRS+= bin
|
||||
# setuid binaries - they use these libraries. PAM needs to be
|
||||
# built dynamically or it tries to build _all_ of the modules
|
||||
# statically - and that ends very badly.
|
||||
CRUNCH_SHLIBS+= -lc -lutil -lcrypt
|
||||
CRUNCH_SHLIBS+= -lc -lutil -lcrypt -lxo -lgpio
|
||||
CRUNCH_LIBS+= -lkvm -lmemstat -lnetgraph
|
||||
CRUNCH_LIBS+= -lcrypt -ledit -ll -ltermcapw
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#define INITHUNKMAX 125 /* initial dynamic allocation size */
|
||||
#define INITLINELEN 4096
|
||||
#define BUFFERSIZE 4096
|
||||
#define LINENUM_MAX LONG_MAX
|
||||
|
||||
#define SCCSPREFIX "s."
|
||||
#define GET "get -e %s"
|
||||
|
@ -78,6 +78,7 @@ static size_t pgets(bool _do_indent);
|
||||
static char *best_name(const struct file_name *, bool);
|
||||
static char *posix_name(const struct file_name *, bool);
|
||||
static size_t num_components(const char *);
|
||||
static LINENUM strtolinenum(char *, char **);
|
||||
|
||||
/*
|
||||
* Prepare to look for the next patch in the patch file.
|
||||
@ -354,7 +355,7 @@ intuit_diff_type(void)
|
||||
stars_this_line = strnEQ(s, "********", 8);
|
||||
if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
|
||||
strnEQ(s, "*** ", 4)) {
|
||||
if (atol(s + 4) == 0)
|
||||
if (strtolinenum(s + 4, &s) == 0)
|
||||
ok_to_create_file = true;
|
||||
/*
|
||||
* If this is a new context diff the character just
|
||||
@ -593,22 +594,25 @@ another_hunk(void)
|
||||
malformed();
|
||||
if (strnEQ(s, "0,0", 3))
|
||||
memmove(s, s + 2, strlen(s + 2) + 1);
|
||||
p_first = (LINENUM) atol(s);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_first = strtolinenum(s, &s);
|
||||
if (*s == ',') {
|
||||
for (;
|
||||
*s && !isdigit((unsigned char)*s); s++)
|
||||
;
|
||||
if (!*s)
|
||||
malformed();
|
||||
p_ptrn_lines = ((LINENUM) atol(s)) - p_first + 1;
|
||||
p_ptrn_lines = strtolinenum(s, &s) - p_first + 1;
|
||||
if (p_ptrn_lines < 0)
|
||||
malformed();
|
||||
} else if (p_first)
|
||||
p_ptrn_lines = 1;
|
||||
else {
|
||||
p_ptrn_lines = 0;
|
||||
p_first = 1;
|
||||
}
|
||||
if (p_first >= LINENUM_MAX - p_ptrn_lines ||
|
||||
p_ptrn_lines >= LINENUM_MAX - 6)
|
||||
malformed();
|
||||
|
||||
/* we need this much at least */
|
||||
p_max = p_ptrn_lines + 6;
|
||||
@ -661,22 +665,25 @@ another_hunk(void)
|
||||
;
|
||||
if (!*s)
|
||||
malformed();
|
||||
p_newfirst = (LINENUM) atol(s);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_newfirst = strtolinenum(s, &s);
|
||||
if (*s == ',') {
|
||||
for (; *s && !isdigit((unsigned char)*s); s++)
|
||||
;
|
||||
if (!*s)
|
||||
malformed();
|
||||
p_repl_lines = ((LINENUM) atol(s)) -
|
||||
p_repl_lines = strtolinenum(s, &s) -
|
||||
p_newfirst + 1;
|
||||
if (p_repl_lines < 0)
|
||||
malformed();
|
||||
} else if (p_newfirst)
|
||||
p_repl_lines = 1;
|
||||
else {
|
||||
p_repl_lines = 0;
|
||||
p_newfirst = 1;
|
||||
}
|
||||
if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
|
||||
p_repl_lines >= LINENUM_MAX - p_end)
|
||||
malformed();
|
||||
p_max = p_repl_lines + p_end;
|
||||
if (p_max > MAXHUNKSIZE)
|
||||
fatal("hunk too large (%ld lines) at line %ld: %s",
|
||||
@ -869,32 +876,28 @@ another_hunk(void)
|
||||
s = buf + 4;
|
||||
if (!*s)
|
||||
malformed();
|
||||
p_first = (LINENUM) atol(s);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_first = strtolinenum(s, &s);
|
||||
if (*s == ',') {
|
||||
p_ptrn_lines = (LINENUM) atol(++s);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_ptrn_lines = strtolinenum(s + 1, &s);
|
||||
} else
|
||||
p_ptrn_lines = 1;
|
||||
if (*s == ' ')
|
||||
s++;
|
||||
if (*s != '+' || !*++s)
|
||||
malformed();
|
||||
p_newfirst = (LINENUM) atol(s);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_newfirst = strtolinenum(s, &s);
|
||||
if (*s == ',') {
|
||||
p_repl_lines = (LINENUM) atol(++s);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_repl_lines = strtolinenum(s + 1, &s);
|
||||
} else
|
||||
p_repl_lines = 1;
|
||||
if (*s == ' ')
|
||||
s++;
|
||||
if (*s != '@')
|
||||
malformed();
|
||||
if (p_first >= LINENUM_MAX - p_ptrn_lines ||
|
||||
p_newfirst > LINENUM_MAX - p_repl_lines ||
|
||||
p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
|
||||
malformed();
|
||||
if (!p_ptrn_lines)
|
||||
p_first++; /* do append rather than insert */
|
||||
p_max = p_ptrn_lines + p_repl_lines + 1;
|
||||
@ -1034,35 +1037,36 @@ another_hunk(void)
|
||||
next_intuit_at(line_beginning, p_input_line);
|
||||
return false;
|
||||
}
|
||||
p_first = (LINENUM) atol(buf);
|
||||
for (s = buf; isdigit((unsigned char)*s); s++)
|
||||
;
|
||||
p_first = strtolinenum(buf, &s);
|
||||
if (*s == ',') {
|
||||
p_ptrn_lines = (LINENUM) atol(++s) - p_first + 1;
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
p_ptrn_lines = strtolinenum(s + 1, &s) - p_first + 1;
|
||||
if (p_ptrn_lines < 0)
|
||||
malformed();
|
||||
} else
|
||||
p_ptrn_lines = (*s != 'a');
|
||||
hunk_type = *s;
|
||||
if (hunk_type == 'a')
|
||||
p_first++; /* do append rather than insert */
|
||||
min = (LINENUM) atol(++s);
|
||||
for (; isdigit((unsigned char)*s); s++)
|
||||
;
|
||||
min = strtolinenum(s + 1, &s);
|
||||
if (*s == ',')
|
||||
max = (LINENUM) atol(++s);
|
||||
max = strtolinenum(s + 1, &s);
|
||||
else
|
||||
max = min;
|
||||
if (min < 0 || min > max || max - min == LINENUM_MAX)
|
||||
malformed();
|
||||
if (hunk_type == 'd')
|
||||
min++;
|
||||
p_end = p_ptrn_lines + 1 + max - min + 1;
|
||||
p_newfirst = min;
|
||||
p_repl_lines = max - min + 1;
|
||||
if (p_newfirst > LINENUM_MAX - p_repl_lines ||
|
||||
p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
|
||||
malformed();
|
||||
p_end = p_ptrn_lines + p_repl_lines + 1;
|
||||
if (p_end > MAXHUNKSIZE)
|
||||
fatal("hunk too large (%ld lines) at line %ld: %s",
|
||||
p_end, p_input_line, buf);
|
||||
while (p_end >= hunkmax)
|
||||
grow_hunkmax();
|
||||
p_newfirst = min;
|
||||
p_repl_lines = max - min + 1;
|
||||
snprintf(buf, buf_size, "*** %ld,%ld\n", p_first,
|
||||
p_first + p_ptrn_lines - 1);
|
||||
p_line[0] = savestr(buf);
|
||||
@ -1582,3 +1586,36 @@ num_components(const char *path)
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert number at NPTR into LINENUM and save address of first
|
||||
* character that is not a digit in ENDPTR. If conversion is not
|
||||
* possible, call fatal.
|
||||
*/
|
||||
static LINENUM
|
||||
strtolinenum(char *nptr, char **endptr)
|
||||
{
|
||||
LINENUM rv;
|
||||
char c;
|
||||
char *p;
|
||||
const char *errstr;
|
||||
|
||||
for (p = nptr; isdigit((unsigned char)*p); p++)
|
||||
;
|
||||
|
||||
if (p == nptr)
|
||||
malformed();
|
||||
|
||||
c = *p;
|
||||
*p = '\0';
|
||||
|
||||
rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
fatal("invalid line number at line %ld: `%s' is %s\n",
|
||||
p_input_line, nptr, errstr);
|
||||
|
||||
*p = c;
|
||||
*endptr = p;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ miss(NODE *p, char *tail)
|
||||
miss(p->child, tp + 1);
|
||||
*tp = '\0';
|
||||
|
||||
if (!create)
|
||||
if (!create && !uflag)
|
||||
continue;
|
||||
if (chown(path, p->st_uid, p->st_gid) == -1) {
|
||||
serr = errno;
|
||||
|
@ -5,10 +5,17 @@ TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.sbin/useradd
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/usr.sbin/pw
|
||||
|
||||
ATF_TESTS_SH= pw_delete pw_lock pw_modify pw_etcdir
|
||||
ATF_TESTS_SH= pw_etcdir \
|
||||
pw_lock \
|
||||
pw_groupdel \
|
||||
pw_groupmod \
|
||||
pw_useradd \
|
||||
pw_userdel \
|
||||
pw_usermod
|
||||
|
||||
TEST_METADATA.pw_delete+= required_user="root"
|
||||
TEST_METADATA.pw_modify+= required_user="root"
|
||||
.for tp in ${ATF_TESTS_SH}
|
||||
TEST_METADATA.${tp}+= required_user="root"
|
||||
.endfor
|
||||
|
||||
FILES= group helper_functions.shin master.passwd
|
||||
FILESDIR= ${TESTSDIR}
|
||||
|
24
usr.sbin/pw/tests/pw_groupdel.sh
Executable file
24
usr.sbin/pw/tests/pw_groupdel.sh
Executable file
@ -0,0 +1,24 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Import helper functions
|
||||
. $(atf_get_srcdir)/helper_functions.shin
|
||||
|
||||
|
||||
# Test to make sure we do not accidentially delete wheel when trying to delete
|
||||
# an unknown group
|
||||
atf_test_case group_do_not_delete_wheel_if_group_unknown
|
||||
group_do_not_delete_wheel_if_group_unknown_head() {
|
||||
atf_set "descr" "Make sure we do not consider gid 0 an unknown group"
|
||||
}
|
||||
group_do_not_delete_wheel_if_group_unknown_body() {
|
||||
populate_etc_skel
|
||||
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
|
||||
atf_check -e inline:"pw: -g expects a number\n" -s exit:64 -x \
|
||||
${PW} groupdel -g I_do_not_exist
|
||||
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
|
||||
}
|
||||
|
||||
|
||||
atf_init_test_cases() {
|
||||
atf_add_test_case group_do_not_delete_wheel_if_group_unknown
|
||||
}
|
40
usr.sbin/pw/tests/pw_useradd.sh
Executable file
40
usr.sbin/pw/tests/pw_useradd.sh
Executable file
@ -0,0 +1,40 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Import helper functions
|
||||
. $(atf_get_srcdir)/helper_functions.shin
|
||||
|
||||
# Test add user
|
||||
atf_test_case user_add
|
||||
user_add_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:0 ${PW} useradd test
|
||||
atf_check -s exit:0 -o match:"^test:.*" \
|
||||
grep "^test:.*" $HOME/master.passwd
|
||||
}
|
||||
|
||||
|
||||
atf_test_case user_add_comments
|
||||
user_add_comments_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:0 ${PW} useradd test -c "Test User,work,123,456"
|
||||
atf_check -s exit:0 -o match:"^test:.*:Test User,work,123,456:" \
|
||||
grep "^test:.*:Test User,work,123,456:" $HOME/master.passwd
|
||||
}
|
||||
|
||||
atf_test_case user_add_comments_invalid
|
||||
user_add_comments_invalid_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:65 -e match:"invalid character" \
|
||||
${PW} useradd test -c "Test User,work,123:456,456"
|
||||
atf_check -s exit:1 -o empty \
|
||||
grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd
|
||||
}
|
||||
|
||||
atf_init_test_cases() {
|
||||
atf_add_test_case user_add
|
||||
atf_add_test_case user_add_comments
|
||||
atf_add_test_case user_add_comments_invalid
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
# Import helper functions
|
||||
. $(atf_get_srcdir)/helper_functions.shin
|
||||
|
||||
|
||||
# Test that a user can be deleted when another user is part of this
|
||||
# user's default group and does not go into an infinate loop.
|
||||
# PR: 191427
|
||||
@ -18,30 +19,19 @@ rmuser_seperate_group_body() {
|
||||
${PW} userdel test || atf_fail "Delete the test user"
|
||||
}
|
||||
|
||||
atf_test_case group_do_not_delete_wheel_if_group_unknown
|
||||
group_do_not_delete_wheel_if_group_unknown_head() {
|
||||
atf_set "descr" "Make sure we do not consider gid 0 an unknown group"
|
||||
}
|
||||
|
||||
group_do_not_delete_wheel_if_group_unknown_body() {
|
||||
populate_etc_skel
|
||||
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
|
||||
atf_check -e inline:"pw: -g expects a number\n" -s exit:64 -x ${PW} groupdel -g I_do_not_exist
|
||||
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
|
||||
}
|
||||
|
||||
atf_test_case user_do_not_try_to_delete_root_if_user_unknown
|
||||
user_do_not_try_to_delete_root_if_user_unknown_head() {
|
||||
atf_set "descr" "Make sure not to try to remove root if deleting an unknown user"
|
||||
atf_set "descr" \
|
||||
"Make sure not to try to remove root if deleting an unknown user"
|
||||
}
|
||||
|
||||
user_do_not_try_to_delete_root_if_user_unknown_body() {
|
||||
populate_etc_skel
|
||||
atf_check -e inline:"pw: -u expects a number\n" -s exit:64 -x ${PW} userdel -u plop
|
||||
atf_check -e inline:"pw: -u expects a number\n" -s exit:64 -x \
|
||||
${PW} userdel -u plop
|
||||
}
|
||||
|
||||
atf_init_test_cases() {
|
||||
atf_add_test_case rmuser_seperate_group
|
||||
atf_add_test_case group_do_not_delete_wheel_if_group_unknown
|
||||
atf_add_test_case user_do_not_try_to_delete_root_if_user_unknown
|
||||
}
|
56
usr.sbin/pw/tests/pw_usermod.sh
Executable file
56
usr.sbin/pw/tests/pw_usermod.sh
Executable file
@ -0,0 +1,56 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Import helper functions
|
||||
. $(atf_get_srcdir)/helper_functions.shin
|
||||
|
||||
# Test modifying a user
|
||||
atf_test_case user_mod
|
||||
user_mod_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:67 -e match:"no such user" ${PW} usermod test
|
||||
atf_check -s exit:0 ${PW} useradd test
|
||||
atf_check -s exit:0 ${PW} usermod test
|
||||
atf_check -s exit:0 -o match:"^test:.*" \
|
||||
grep "^test:.*" $HOME/master.passwd
|
||||
}
|
||||
|
||||
# Test modifying a user with comments
|
||||
atf_test_case user_mod_comments
|
||||
user_mod_comments_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:0 ${PW} useradd test -c "Test User,home,123,456"
|
||||
atf_check -s exit:0 ${PW} usermod test -c "Test User,work,123,456"
|
||||
atf_check -s exit:0 -o match:"^test:.*:Test User,work,123,456:" \
|
||||
grep "^test:.*:Test User,work,123,456:" $HOME/master.passwd
|
||||
}
|
||||
|
||||
# Test modifying a user with invalid comments
|
||||
atf_test_case user_mod_comments_invalid
|
||||
user_mod_comments_invalid_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:0 ${PW} useradd test
|
||||
atf_check -s exit:65 -e match:"invalid character" \
|
||||
${PW} usermod test -c "Test User,work,123:456,456"
|
||||
atf_check -s exit:1 -o empty \
|
||||
grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd
|
||||
}
|
||||
|
||||
# Test modifying a user name with -l
|
||||
atf_test_case user_mod_name
|
||||
user_mod_name_body() {
|
||||
populate_etc_skel
|
||||
|
||||
atf_check -s exit:0 ${PW} useradd foo
|
||||
atf_check -s exit:0 ${PW} usermod foo -l "bar"
|
||||
atf_check -s exit:0 -o match:"^bar:.*" \
|
||||
grep "^bar:.*" $HOME/master.passwd
|
||||
}
|
||||
atf_init_test_cases() {
|
||||
atf_add_test_case user_mod
|
||||
atf_add_test_case user_mod_comments
|
||||
atf_add_test_case user_mod_comments_invalid
|
||||
atf_add_test_case user_mod_name
|
||||
}
|
Loading…
Reference in New Issue
Block a user