MFhead @ r275663

This commit is contained in:
Enji Cooper 2014-12-10 06:43:16 +00:00
commit f0d7e7f714
66 changed files with 2865 additions and 424 deletions

View File

@ -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
#

View File

@ -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; \

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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');

View File

@ -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
+}

View File

@ -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

View File

@ -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;

View File

@ -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 $?
}

View File

@ -168,6 +168,8 @@ Gigaset USB Adapter 54
.It
Inventel UR045G
.It
Netgear WG111v1 (rev2)
.It
SMC EZ ConnectG SMC2862W-G
.It
Sagem XG703A

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -123,6 +123,7 @@ device spibus
device beri_ring
device beri_mem
device beri_vtblk
device vtbe
device altera_pio
# Ethernet

View File

@ -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";
};

View File

@ -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

View File

@ -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 *);

View File

@ -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)

View File

@ -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

View 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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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),

View File

@ -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

View File

@ -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),

View File

@ -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);
}
}
}
}

View File

@ -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.

View 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
View 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);

View File

@ -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))

View File

@ -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);

View File

@ -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));

View File

@ -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)) {

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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);
/*

View File

@ -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

View File

@ -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

View File

@ -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 *);

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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;
}

View File

@ -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>

View File

@ -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,

View File

@ -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);

View File

@ -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);
}

View File

@ -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
View 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__ */

View File

@ -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

View File

@ -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"

View File

@ -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;
}

View File

@ -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;

View File

@ -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}

View 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
View 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
}

View File

@ -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
View 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
}