IFC @r273214
This commit is contained in:
commit
e1a172e1c2
@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 5, 2013
|
||||
.Dd September 22, 2014
|
||||
.Dt PING6 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -65,6 +65,12 @@ packets to network hosts
|
||||
.Op Fl i Ar wait
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl x Ar waittime
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl X Ar timeout
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl l Ar preload
|
||||
.Ek
|
||||
.Bk -words
|
||||
@ -191,6 +197,15 @@ The default is to wait for one second between each packet.
|
||||
This option is incompatible with the
|
||||
.Fl f
|
||||
option.
|
||||
.It Fl x Ar waittime
|
||||
Time in milliseconds to wait for a reply for each packet sent.
|
||||
If a reply arrives later,
|
||||
the packet is not printed as replied,
|
||||
but considered as replied when calculating statistics.
|
||||
.It Fl X Ar timeout
|
||||
Specify a timeout,
|
||||
in seconds,
|
||||
before ping exits regardless of how many packets have been received.
|
||||
.It Fl l Ar preload
|
||||
If
|
||||
.Ar preload
|
||||
|
@ -152,6 +152,8 @@ struct tv32 {
|
||||
#define DEFDATALEN ICMP6ECHOTMLEN
|
||||
#define MAXDATALEN MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
|
||||
#define NROUTES 9 /* number of record route slots */
|
||||
#define MAXWAIT 10000 /* max ms to wait for response */
|
||||
#define MAXALARM (60 * 60) /* max seconds for alarm timeout */
|
||||
|
||||
#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
|
||||
#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
|
||||
@ -188,6 +190,7 @@ struct tv32 {
|
||||
#define F_MISSED 0x800000
|
||||
#define F_DONTFRAG 0x1000000
|
||||
#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
|
||||
#define F_WAITTIME 0x2000000
|
||||
u_int options;
|
||||
|
||||
#define IN6LEN sizeof(struct in6_addr)
|
||||
@ -228,6 +231,8 @@ long nreceived; /* # of packets we got back */
|
||||
long nrepeats; /* number of duplicates */
|
||||
long ntransmitted; /* sequence # for outbound packets = #sent */
|
||||
int interval = 1000; /* interval between packets in ms */
|
||||
int waittime = MAXWAIT; /* timeout for each packet */
|
||||
long nrcvtimeout = 0; /* # of packets we got back after waittime */
|
||||
|
||||
/* timing */
|
||||
int timing; /* flag to do timing */
|
||||
@ -312,6 +317,7 @@ main(int argc, char *argv[])
|
||||
char *policy_out = NULL;
|
||||
#endif
|
||||
double t;
|
||||
u_long alarmtimeout;
|
||||
size_t rthlen;
|
||||
#ifdef IPV6_USE_MIN_MTU
|
||||
int mflag = 0;
|
||||
@ -321,7 +327,7 @@ main(int argc, char *argv[])
|
||||
memset(&smsghdr, 0, sizeof(smsghdr));
|
||||
memset(&smsgiov, 0, sizeof(smsgiov));
|
||||
|
||||
preload = 0;
|
||||
alarmtimeout = preload = 0;
|
||||
datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
|
||||
#ifndef IPSEC
|
||||
#define ADDOPTS
|
||||
@ -333,7 +339,7 @@ main(int argc, char *argv[])
|
||||
#endif /*IPSEC_POLICY_IPSEC*/
|
||||
#endif
|
||||
while ((ch = getopt(argc, argv,
|
||||
"a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwW" ADDOPTS)) != -1) {
|
||||
"a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwWx:X:" ADDOPTS)) != -1) {
|
||||
#undef ADDOPTS
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
@ -541,6 +547,24 @@ main(int argc, char *argv[])
|
||||
options &= ~F_NOUSERDATA;
|
||||
options |= F_FQDNOLD;
|
||||
break;
|
||||
case 'x':
|
||||
t = strtod(optarg, &e);
|
||||
if (*e || e == optarg || t > (double)INT_MAX)
|
||||
err(EX_USAGE, "invalid timing interval: `%s'",
|
||||
optarg);
|
||||
options |= F_WAITTIME;
|
||||
waittime = (int)t;
|
||||
break;
|
||||
case 'X':
|
||||
alarmtimeout = strtoul(optarg, &e, 0);
|
||||
if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX))
|
||||
errx(EX_USAGE, "invalid timeout: `%s'",
|
||||
optarg);
|
||||
if (alarmtimeout > MAXALARM)
|
||||
errx(EX_USAGE, "invalid timeout: `%s' > %d",
|
||||
optarg, MAXALARM);
|
||||
alarm((int)alarmtimeout);
|
||||
break;
|
||||
#ifdef IPSEC
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
case 'P':
|
||||
@ -1057,6 +1081,10 @@ main(int argc, char *argv[])
|
||||
err(EX_OSERR, "sigaction SIGINFO");
|
||||
seeninfo = 0;
|
||||
#endif
|
||||
if (alarmtimeout > 0) {
|
||||
if (sigaction(SIGALRM, &si_sa, 0) == -1)
|
||||
err(EX_OSERR, "sigaction SIGALRM");
|
||||
}
|
||||
if (options & F_FLOOD) {
|
||||
intvl.tv_sec = 0;
|
||||
intvl.tv_usec = 10000;
|
||||
@ -1157,17 +1185,18 @@ main(int argc, char *argv[])
|
||||
/*
|
||||
* If we're not transmitting any more packets,
|
||||
* change the timer to wait two round-trip times
|
||||
* if we've received any packets or ten seconds
|
||||
* if we haven't.
|
||||
* if we've received any packets or (waittime)
|
||||
* milliseconds if we haven't.
|
||||
*/
|
||||
#define MAXWAIT 10
|
||||
intvl.tv_usec = 0;
|
||||
if (nreceived) {
|
||||
intvl.tv_sec = 2 * tmax / 1000;
|
||||
if (intvl.tv_sec == 0)
|
||||
intvl.tv_sec = 1;
|
||||
} else
|
||||
intvl.tv_sec = MAXWAIT;
|
||||
} else {
|
||||
intvl.tv_sec = waittime / 1000;
|
||||
intvl.tv_usec = waittime % 1000 * 1000;
|
||||
}
|
||||
}
|
||||
gettimeofday(&last, NULL);
|
||||
if (ntransmitted - nreceived - 1 > nmissedmax) {
|
||||
@ -1181,6 +1210,7 @@ main(int argc, char *argv[])
|
||||
si_sa.sa_flags = 0;
|
||||
si_sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGINT, &si_sa, 0);
|
||||
sigaction(SIGALRM, &si_sa, 0);
|
||||
summary();
|
||||
|
||||
if (res != NULL)
|
||||
@ -1198,6 +1228,7 @@ onsignal(int sig)
|
||||
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
case SIGALRM:
|
||||
seenint++;
|
||||
break;
|
||||
#ifdef SIGINFO
|
||||
@ -1521,6 +1552,11 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
|
||||
if (options & F_QUIET)
|
||||
return;
|
||||
|
||||
if (options & F_WAITTIME && triptime > waittime) {
|
||||
++nrcvtimeout;
|
||||
return;
|
||||
}
|
||||
|
||||
if (options & F_FLOOD)
|
||||
(void)write(STDOUT_FILENO, &BSPACE, 1);
|
||||
else {
|
||||
@ -2216,6 +2252,8 @@ summary(void)
|
||||
((((double)ntransmitted - nreceived) * 100.0) /
|
||||
ntransmitted));
|
||||
}
|
||||
if (nrcvtimeout)
|
||||
printf(", %ld packets out of wait time", nrcvtimeout);
|
||||
(void)putchar('\n');
|
||||
if (nreceived && timing) {
|
||||
/* Only display average to microseconds */
|
||||
@ -2741,6 +2779,7 @@ usage(void)
|
||||
#endif
|
||||
"\n"
|
||||
" [-p pattern] [-S sourceaddr] [-s packetsize] "
|
||||
"[hops ...] host\n");
|
||||
"[-x waittime]\n"
|
||||
" [-X timeout] [hops ...] host\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
#include <machine/asmacros.h>
|
||||
|
||||
#include "svm_assym.s"
|
||||
#include "svm_assym.h"
|
||||
|
||||
/*
|
||||
* Be friendly to DTrace FBT's prologue/epilogue pattern matching.
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include <machine/asmacros.h>
|
||||
|
||||
#include "vmx_assym.s"
|
||||
#include "vmx_assym.h"
|
||||
|
||||
#ifdef SMP
|
||||
#define LK lock ;
|
||||
|
@ -3231,7 +3231,8 @@ net/if_ethersubr.c optional ether
|
||||
net/if_faith.c optional faith
|
||||
net/if_fddisubr.c optional fddi
|
||||
net/if_fwsubr.c optional fwip
|
||||
net/if_gif.c optional gif inet | gif inet6 | netgraph_gif
|
||||
net/if_gif.c optional gif inet | gif inet6 | \
|
||||
netgraph_gif inet | netgraph_gif inet6
|
||||
net/if_gre.c optional gre inet
|
||||
net/if_iso88025subr.c optional token
|
||||
net/if_lagg.c optional lagg
|
||||
@ -3357,7 +3358,7 @@ netgraph/ng_eiface.c optional netgraph_eiface
|
||||
netgraph/ng_ether.c optional netgraph_ether
|
||||
netgraph/ng_ether_echo.c optional netgraph_ether_echo
|
||||
netgraph/ng_frame_relay.c optional netgraph_frame_relay
|
||||
netgraph/ng_gif.c optional netgraph_gif
|
||||
netgraph/ng_gif.c optional netgraph_gif inet6 | netgraph_gif inet
|
||||
netgraph/ng_gif_demux.c optional netgraph_gif_demux
|
||||
netgraph/ng_hole.c optional netgraph_hole
|
||||
netgraph/ng_iface.c optional netgraph_iface
|
||||
|
@ -550,7 +550,6 @@ autofs_ioctl_request(struct autofs_daemon_request *adr)
|
||||
&autofs_softc->sc_lock);
|
||||
if (error != 0) {
|
||||
sx_xunlock(&autofs_softc->sc_lock);
|
||||
AUTOFS_DEBUG("failed with error %d", error);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +61,9 @@ static void
|
||||
g_confdot_provider(struct sbuf *sb, struct g_provider *pp)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "z%p [shape=hexagon,label=\"%s\\nr%dw%de%d\\nerr#%d\"];\n",
|
||||
pp, pp->name, pp->acr, pp->acw, pp->ace, pp->error);
|
||||
sbuf_printf(sb, "z%p [shape=hexagon,label=\"%s\\nr%dw%de%d\\nerr#%d\\n"
|
||||
"sector=%u\\nstripe=%u\"];\n", pp, pp->name, pp->acr, pp->acw,
|
||||
pp->ace, pp->error, pp->sectorsize, pp->stripesize);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3,6 +3,7 @@
|
||||
KMOD= vmm
|
||||
|
||||
SRCS= opt_acpi.h opt_ddb.h device_if.h bus_if.h pci_if.h
|
||||
SRCS+= vmx_assym.h svm_assym.h
|
||||
|
||||
CFLAGS+= -DVMM_KEEP_STATS -DSMP
|
||||
CFLAGS+= -I${.CURDIR}/../../amd64/vmm
|
||||
@ -39,6 +40,7 @@ SRCS+= iommu.c \
|
||||
SRCS+= ept.c \
|
||||
vmcs.c \
|
||||
vmx_msr.c \
|
||||
vmx_support.S \
|
||||
vmx.c \
|
||||
vtd.c
|
||||
|
||||
@ -46,37 +48,37 @@ SRCS+= ept.c \
|
||||
.PATH: ${.CURDIR}/../../amd64/vmm/amd
|
||||
SRCS+= vmcb.c \
|
||||
svm.c \
|
||||
svm_support.S \
|
||||
npt.c \
|
||||
amdv.c \
|
||||
svm_msr.c
|
||||
|
||||
OBJS= vmx_support.o svm_support.o
|
||||
CLEANFILES= vmx_assym.h vmx_genassym.o svm_assym.h svm_genassym.o
|
||||
|
||||
CLEANFILES= vmx_assym.s vmx_genassym.o svm_assym.s svm_genassym.o
|
||||
|
||||
vmx_assym.s: vmx_genassym.o
|
||||
vmx_assym.h: vmx_genassym.o
|
||||
.if exists(@)
|
||||
vmx_assym.s: @/kern/genassym.sh
|
||||
vmx_assym.h: @/kern/genassym.sh
|
||||
.endif
|
||||
sh @/kern/genassym.sh vmx_genassym.o > ${.TARGET}
|
||||
|
||||
svm_assym.s: svm_genassym.o
|
||||
svm_assym.h: svm_genassym.o
|
||||
.if exists(@)
|
||||
svm_assym.s: @/kern/genassym.sh
|
||||
svm_assym.h: @/kern/genassym.sh
|
||||
.endif
|
||||
sh @/kern/genassym.sh svm_genassym.o > ${.TARGET}
|
||||
|
||||
vmx_support.o: vmx_support.S vmx_assym.s
|
||||
vmx_support.o:
|
||||
${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
|
||||
${.IMPSRC} -o ${.TARGET}
|
||||
|
||||
svm_support.o: svm_support.S svm_assym.s
|
||||
svm_support.o:
|
||||
${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
|
||||
${.IMPSRC} -o ${.TARGET}
|
||||
|
||||
vmx_genassym.o: vmx_genassym.c @ machine x86
|
||||
vmx_genassym.o:
|
||||
${CC} -c ${CFLAGS:N-fno-common} ${.IMPSRC}
|
||||
|
||||
svm_genassym.o: svm_genassym.c @ machine x86
|
||||
svm_genassym.o:
|
||||
${CC} -c ${CFLAGS:N-fno-common} ${.IMPSRC}
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -569,9 +569,22 @@ lagg_clone_destroy(struct ifnet *ifp)
|
||||
static void
|
||||
lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct lagg_port lp;
|
||||
|
||||
if (memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0)
|
||||
return;
|
||||
|
||||
LAGG_WLOCK_ASSERT(sc);
|
||||
/*
|
||||
* Set the link layer address on the lagg interface.
|
||||
* lagg_proto_lladdr() notifies the MAC change to
|
||||
* the aggregation protocol. iflladdr_event handler which
|
||||
* may trigger gratuitous ARPs for INET will be handled in
|
||||
* a taskqueue.
|
||||
*/
|
||||
bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
|
||||
lagg_proto_lladdr(sc);
|
||||
|
||||
bzero(&lp, sizeof(lp));
|
||||
lp.lp_ifp = sc->sc_ifp;
|
||||
@ -625,11 +638,13 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr)
|
||||
struct ifnet *ifp = lp->lp_ifp;
|
||||
struct lagg_llq *llq;
|
||||
int pending = 0;
|
||||
int primary;
|
||||
|
||||
LAGG_WLOCK_ASSERT(sc);
|
||||
|
||||
if (lp->lp_detaching ||
|
||||
memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0)
|
||||
primary = (sc->sc_primary->lp_ifp == ifp) ? 1 : 0;
|
||||
if (primary == 0 && (lp->lp_detaching ||
|
||||
memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0))
|
||||
return;
|
||||
|
||||
/* Check to make sure its not already queued to be changed */
|
||||
@ -648,7 +663,7 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr)
|
||||
|
||||
/* Update the lladdr even if pending, it may have changed */
|
||||
llq->llq_ifp = ifp;
|
||||
llq->llq_primary = (sc->sc_primary->lp_ifp == ifp) ? 1 : 0;
|
||||
llq->llq_primary = primary;
|
||||
bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN);
|
||||
|
||||
if (!pending)
|
||||
@ -692,23 +707,8 @@ lagg_port_setlladdr(void *arg, int pending)
|
||||
if (error)
|
||||
printf("%s: setlladdr failed on %s\n", __func__,
|
||||
ifp->if_xname);
|
||||
} else {
|
||||
/*
|
||||
* Set the link layer address on the lagg interface.
|
||||
* lagg_proto_lladdr() notifies the MAC change to
|
||||
* the aggregation protocol. iflladdr_event handler
|
||||
* may trigger gratuitous ARPs for INET.
|
||||
*/
|
||||
if (memcmp(llq->llq_lladdr, IF_LLADDR(ifp),
|
||||
ETHER_ADDR_LEN) != 0) {
|
||||
bcopy(llq->llq_lladdr, IF_LLADDR(ifp),
|
||||
ETHER_ADDR_LEN);
|
||||
LAGG_WLOCK(sc);
|
||||
lagg_proto_lladdr(sc);
|
||||
LAGG_WUNLOCK(sc);
|
||||
EVENTHANDLER_INVOKE(iflladdr_event, ifp);
|
||||
}
|
||||
}
|
||||
} else
|
||||
EVENTHANDLER_INVOKE(iflladdr_event, ifp);
|
||||
CURVNET_RESTORE();
|
||||
head = SLIST_NEXT(llq, llq_entries);
|
||||
free(llq, M_DEVBUF);
|
||||
@ -742,34 +742,6 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
|
||||
if (ifp->if_type != IFT_ETHER)
|
||||
return (EPROTONOSUPPORT);
|
||||
|
||||
#ifdef INET6
|
||||
/*
|
||||
* The member interface should not have inet6 address because
|
||||
* two interfaces with a valid link-local scope zone must not be
|
||||
* merged in any form. This restriction is needed to
|
||||
* prevent violation of link-local scope zone. Attempts to
|
||||
* add a member interface which has inet6 addresses triggers
|
||||
* removal of all inet6 addresses on the member interface.
|
||||
*/
|
||||
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
|
||||
if (in6ifa_llaonifp(lp->lp_ifp)) {
|
||||
in6_ifdetach(lp->lp_ifp);
|
||||
if_printf(sc->sc_ifp,
|
||||
"IPv6 addresses on %s have been removed "
|
||||
"before adding it as a member to prevent "
|
||||
"IPv6 address scope violation.\n",
|
||||
lp->lp_ifp->if_xname);
|
||||
}
|
||||
}
|
||||
if (in6ifa_llaonifp(ifp)) {
|
||||
in6_ifdetach(ifp);
|
||||
if_printf(sc->sc_ifp,
|
||||
"IPv6 addresses on %s have been removed "
|
||||
"before adding it as a member to prevent "
|
||||
"IPv6 address scope violation.\n",
|
||||
ifp->if_xname);
|
||||
}
|
||||
#endif
|
||||
/* Allow the first Ethernet member to define the MTU */
|
||||
if (SLIST_EMPTY(&sc->sc_ports))
|
||||
sc->sc_ifp->if_mtu = ifp->if_mtu;
|
||||
@ -1414,6 +1386,26 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
#ifdef INET6
|
||||
/*
|
||||
* A laggport interface should not have inet6 address
|
||||
* because two interfaces with a valid link-local
|
||||
* scope zone must not be merged in any form. This
|
||||
* restriction is needed to prevent violation of
|
||||
* link-local scope zone. Attempts to add a laggport
|
||||
* interface which has inet6 addresses triggers
|
||||
* removal of all inet6 addresses on the member
|
||||
* interface.
|
||||
*/
|
||||
if (in6ifa_llaonifp(tpif)) {
|
||||
in6_ifdetach(tpif);
|
||||
if_printf(sc->sc_ifp,
|
||||
"IPv6 addresses on %s have been removed "
|
||||
"before adding it as a member to prevent "
|
||||
"IPv6 address scope violation.\n",
|
||||
tpif->if_xname);
|
||||
}
|
||||
#endif
|
||||
LAGG_WLOCK(sc);
|
||||
error = lagg_port_create(sc, tpif);
|
||||
LAGG_WUNLOCK(sc);
|
||||
|
@ -55,8 +55,7 @@ __FBSDID("$FreeBSD$");
|
||||
enum blockop {
|
||||
BOP_READ,
|
||||
BOP_WRITE,
|
||||
BOP_FLUSH,
|
||||
BOP_CANCEL
|
||||
BOP_FLUSH
|
||||
};
|
||||
|
||||
enum blockstat {
|
||||
@ -159,9 +158,6 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be)
|
||||
break;
|
||||
case BOP_FLUSH:
|
||||
break;
|
||||
case BOP_CANCEL:
|
||||
err = EINTR;
|
||||
break;
|
||||
default:
|
||||
err = EINVAL;
|
||||
break;
|
||||
@ -356,9 +352,28 @@ blockif_flush(struct blockif_ctxt *bc, struct blockif_req *breq)
|
||||
int
|
||||
blockif_cancel(struct blockif_ctxt *bc, struct blockif_req *breq)
|
||||
{
|
||||
struct blockif_elem *be;
|
||||
|
||||
assert(bc->bc_magic == BLOCKIF_SIG);
|
||||
return (blockif_request(bc, breq, BOP_CANCEL));
|
||||
|
||||
pthread_mutex_lock(&bc->bc_mtx);
|
||||
TAILQ_FOREACH(be, &bc->bc_inuseq, be_link) {
|
||||
if (be->be_req == breq)
|
||||
break;
|
||||
}
|
||||
if (be == NULL) {
|
||||
pthread_mutex_unlock(&bc->bc_mtx);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&bc->bc_inuseq, be, be_link);
|
||||
be->be_status = BST_FREE;
|
||||
be->be_req = NULL;
|
||||
TAILQ_INSERT_TAIL(&bc->bc_freeq, be, be_link);
|
||||
bc->bc_req_count--;
|
||||
pthread_mutex_unlock(&bc->bc_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <pthread_np.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "bhyverun.h"
|
||||
@ -115,7 +116,8 @@ static FILE *dbg;
|
||||
struct ahci_ioreq {
|
||||
struct blockif_req io_req;
|
||||
struct ahci_port *io_pr;
|
||||
STAILQ_ENTRY(ahci_ioreq) io_list;
|
||||
STAILQ_ENTRY(ahci_ioreq) io_flist;
|
||||
TAILQ_ENTRY(ahci_ioreq) io_blist;
|
||||
uint8_t *cfis;
|
||||
uint32_t len;
|
||||
uint32_t done;
|
||||
@ -160,6 +162,7 @@ struct ahci_port {
|
||||
struct ahci_ioreq *ioreq;
|
||||
int ioqsz;
|
||||
STAILQ_HEAD(ahci_fhead, ahci_ioreq) iofhd;
|
||||
TAILQ_HEAD(ahci_bhead, ahci_ioreq) iobhd;
|
||||
};
|
||||
|
||||
struct ahci_cmd_hdr {
|
||||
@ -359,6 +362,68 @@ ahci_write_reset_fis_d2h(struct ahci_port *p)
|
||||
ahci_write_fis(p, FIS_TYPE_REGD2H, fis);
|
||||
}
|
||||
|
||||
static void
|
||||
ahci_check_stopped(struct ahci_port *p)
|
||||
{
|
||||
/*
|
||||
* If we are no longer processing the command list and nothing
|
||||
* is in-flight, clear the running bit.
|
||||
*/
|
||||
if (!(p->cmd & AHCI_P_CMD_ST)) {
|
||||
if (p->pending == 0)
|
||||
p->cmd &= ~(AHCI_P_CMD_CR | AHCI_P_CMD_CCS_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ahci_port_stop(struct ahci_port *p)
|
||||
{
|
||||
struct ahci_ioreq *aior;
|
||||
uint8_t *cfis;
|
||||
int slot;
|
||||
int ncq;
|
||||
int error;
|
||||
|
||||
assert(pthread_mutex_isowned_np(&p->pr_sc->mtx));
|
||||
|
||||
TAILQ_FOREACH(aior, &p->iobhd, io_blist) {
|
||||
/*
|
||||
* Try to cancel the outstanding blockif request.
|
||||
*/
|
||||
error = blockif_cancel(p->bctx, &aior->io_req);
|
||||
if (error != 0)
|
||||
continue;
|
||||
|
||||
slot = aior->slot;
|
||||
cfis = aior->cfis;
|
||||
if (cfis[2] == ATA_WRITE_FPDMA_QUEUED ||
|
||||
cfis[2] == ATA_READ_FPDMA_QUEUED)
|
||||
ncq = 1;
|
||||
|
||||
if (ncq)
|
||||
p->sact &= ~(1 << slot);
|
||||
else
|
||||
p->ci &= ~(1 << slot);
|
||||
|
||||
/*
|
||||
* This command is now done.
|
||||
*/
|
||||
p->pending &= ~(1 << slot);
|
||||
|
||||
/*
|
||||
* Delete the blockif request from the busy list
|
||||
*/
|
||||
TAILQ_REMOVE(&p->iobhd, aior, io_blist);
|
||||
|
||||
/*
|
||||
* Move the blockif request back to the free list
|
||||
*/
|
||||
STAILQ_INSERT_TAIL(&p->iofhd, aior, io_flist);
|
||||
}
|
||||
|
||||
ahci_check_stopped(p);
|
||||
}
|
||||
|
||||
static void
|
||||
ahci_port_reset(struct ahci_port *pr)
|
||||
{
|
||||
@ -492,7 +557,7 @@ ahci_handle_dma(struct ahci_port *p, int slot, uint8_t *cfis, uint32_t done,
|
||||
*/
|
||||
aior = STAILQ_FIRST(&p->iofhd);
|
||||
assert(aior != NULL);
|
||||
STAILQ_REMOVE_HEAD(&p->iofhd, io_list);
|
||||
STAILQ_REMOVE_HEAD(&p->iofhd, io_flist);
|
||||
aior->cfis = cfis;
|
||||
aior->slot = slot;
|
||||
aior->len = len;
|
||||
@ -503,14 +568,20 @@ ahci_handle_dma(struct ahci_port *p, int slot, uint8_t *cfis, uint32_t done,
|
||||
if (iovcnt > BLOCKIF_IOV_MAX) {
|
||||
aior->prdtl = iovcnt - BLOCKIF_IOV_MAX;
|
||||
iovcnt = BLOCKIF_IOV_MAX;
|
||||
/*
|
||||
* Mark this command in-flight.
|
||||
*/
|
||||
p->pending |= 1 << slot;
|
||||
} else
|
||||
aior->prdtl = 0;
|
||||
breq->br_iovcnt = iovcnt;
|
||||
|
||||
/*
|
||||
* Mark this command in-flight.
|
||||
*/
|
||||
p->pending |= 1 << slot;
|
||||
|
||||
/*
|
||||
* Stuff request onto busy list
|
||||
*/
|
||||
TAILQ_INSERT_HEAD(&p->iobhd, aior, io_blist);
|
||||
|
||||
/*
|
||||
* Build up the iovec based on the prdt
|
||||
*/
|
||||
@ -546,7 +617,7 @@ ahci_handle_flush(struct ahci_port *p, int slot, uint8_t *cfis)
|
||||
*/
|
||||
aior = STAILQ_FIRST(&p->iofhd);
|
||||
assert(aior != NULL);
|
||||
STAILQ_REMOVE_HEAD(&p->iofhd, io_list);
|
||||
STAILQ_REMOVE_HEAD(&p->iofhd, io_flist);
|
||||
aior->cfis = cfis;
|
||||
aior->slot = slot;
|
||||
aior->len = 0;
|
||||
@ -554,6 +625,16 @@ ahci_handle_flush(struct ahci_port *p, int slot, uint8_t *cfis)
|
||||
aior->prdtl = 0;
|
||||
breq = &aior->io_req;
|
||||
|
||||
/*
|
||||
* Mark this command in-flight.
|
||||
*/
|
||||
p->pending |= 1 << slot;
|
||||
|
||||
/*
|
||||
* Stuff request onto busy list
|
||||
*/
|
||||
TAILQ_INSERT_HEAD(&p->iobhd, aior, io_blist);
|
||||
|
||||
err = blockif_flush(p->bctx, breq);
|
||||
assert(err == 0);
|
||||
}
|
||||
@ -961,7 +1042,7 @@ atapi_read(struct ahci_port *p, int slot, uint8_t *cfis,
|
||||
*/
|
||||
aior = STAILQ_FIRST(&p->iofhd);
|
||||
assert(aior != NULL);
|
||||
STAILQ_REMOVE_HEAD(&p->iofhd, io_list);
|
||||
STAILQ_REMOVE_HEAD(&p->iofhd, io_flist);
|
||||
aior->cfis = cfis;
|
||||
aior->slot = slot;
|
||||
aior->len = len;
|
||||
@ -976,6 +1057,16 @@ atapi_read(struct ahci_port *p, int slot, uint8_t *cfis,
|
||||
aior->prdtl = 0;
|
||||
breq->br_iovcnt = iovcnt;
|
||||
|
||||
/*
|
||||
* Mark this command in-flight.
|
||||
*/
|
||||
p->pending |= 1 << slot;
|
||||
|
||||
/*
|
||||
* Stuff request onto busy list
|
||||
*/
|
||||
TAILQ_INSERT_HEAD(&p->iobhd, aior, io_blist);
|
||||
|
||||
/*
|
||||
* Build up the iovec based on the prdt
|
||||
*/
|
||||
@ -1414,10 +1505,15 @@ ata_ioreq_cb(struct blockif_req *br, int err)
|
||||
|
||||
pthread_mutex_lock(&sc->mtx);
|
||||
|
||||
/*
|
||||
* Delete the blockif request from the busy list
|
||||
*/
|
||||
TAILQ_REMOVE(&p->iobhd, aior, io_blist);
|
||||
|
||||
/*
|
||||
* Move the blockif request back to the free list
|
||||
*/
|
||||
STAILQ_INSERT_TAIL(&p->iofhd, aior, io_list);
|
||||
STAILQ_INSERT_TAIL(&p->iofhd, aior, io_flist);
|
||||
|
||||
if (pending && !err) {
|
||||
ahci_handle_dma(p, slot, cfis, aior->done,
|
||||
@ -1438,17 +1534,18 @@ ata_ioreq_cb(struct blockif_req *br, int err)
|
||||
p->serr |= (1 << slot);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command is now complete.
|
||||
*/
|
||||
p->pending &= ~(1 << slot);
|
||||
|
||||
if (ncq) {
|
||||
p->sact &= ~(1 << slot);
|
||||
ahci_write_fis_sdb(p, slot, tfd);
|
||||
} else
|
||||
ahci_write_fis_d2h(p, slot, cfis, tfd);
|
||||
|
||||
/*
|
||||
* This command is now complete.
|
||||
*/
|
||||
p->pending &= ~(1 << slot);
|
||||
|
||||
ahci_check_stopped(p);
|
||||
out:
|
||||
pthread_mutex_unlock(&sc->mtx);
|
||||
DPRINTF("%s exit\n", __func__);
|
||||
@ -1477,10 +1574,15 @@ atapi_ioreq_cb(struct blockif_req *br, int err)
|
||||
|
||||
pthread_mutex_lock(&sc->mtx);
|
||||
|
||||
/*
|
||||
* Delete the blockif request from the busy list
|
||||
*/
|
||||
TAILQ_REMOVE(&p->iobhd, aior, io_blist);
|
||||
|
||||
/*
|
||||
* Move the blockif request back to the free list
|
||||
*/
|
||||
STAILQ_INSERT_TAIL(&p->iofhd, aior, io_list);
|
||||
STAILQ_INSERT_TAIL(&p->iofhd, aior, io_flist);
|
||||
|
||||
if (pending && !err) {
|
||||
atapi_read(p, slot, cfis, aior->done, hdr->prdtl - pending);
|
||||
@ -1500,6 +1602,12 @@ atapi_ioreq_cb(struct blockif_req *br, int err)
|
||||
cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
|
||||
ahci_write_fis_d2h(p, slot, cfis, tfd);
|
||||
|
||||
/*
|
||||
* This command is now complete.
|
||||
*/
|
||||
p->pending &= ~(1 << slot);
|
||||
|
||||
ahci_check_stopped(p);
|
||||
out:
|
||||
pthread_mutex_unlock(&sc->mtx);
|
||||
DPRINTF("%s exit\n", __func__);
|
||||
@ -1526,8 +1634,10 @@ pci_ahci_ioreq_init(struct ahci_port *pr)
|
||||
else
|
||||
vr->io_req.br_callback = atapi_ioreq_cb;
|
||||
vr->io_req.br_param = vr;
|
||||
STAILQ_INSERT_TAIL(&pr->iofhd, vr, io_list);
|
||||
STAILQ_INSERT_TAIL(&pr->iofhd, vr, io_flist);
|
||||
}
|
||||
|
||||
TAILQ_INIT(&pr->iobhd);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1565,9 +1675,7 @@ pci_ahci_port_write(struct pci_ahci_softc *sc, uint64_t offset, uint64_t value)
|
||||
p->cmd = value;
|
||||
|
||||
if (!(value & AHCI_P_CMD_ST)) {
|
||||
p->cmd &= ~(AHCI_P_CMD_CR | AHCI_P_CMD_CCS_MASK);
|
||||
p->ci = 0;
|
||||
p->sact = 0;
|
||||
ahci_port_stop(p);
|
||||
} else {
|
||||
uint64_t clb;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user