diff options
author | neel <neel@FreeBSD.org> | 2014-10-20 02:57:30 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-10-20 02:57:30 +0000 |
commit | dd2febd6f26be95c4b3f1f67b23f53a28885082f (patch) | |
tree | b2c78a90b3492af4d40dfeb9faedeb6bb82208c4 | |
parent | 53c23ba9a2104ef3682a2b22cb1ab9269ca0745d (diff) | |
download | FreeBSD-src-dd2febd6f26be95c4b3f1f67b23f53a28885082f.zip FreeBSD-src-dd2febd6f26be95c4b3f1f67b23f53a28885082f.tar.gz |
IFC @r273214
-rw-r--r-- | sbin/ping6/ping6.8 | 17 | ||||
-rw-r--r-- | sbin/ping6/ping6.c | 55 | ||||
-rw-r--r-- | sys/amd64/vmm/amd/svm_support.S | 2 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx_support.S | 2 | ||||
-rw-r--r-- | sys/conf/files | 5 | ||||
-rw-r--r-- | sys/fs/autofs/autofs.c | 1 | ||||
-rw-r--r-- | sys/geom/geom_dump.c | 5 | ||||
-rw-r--r-- | sys/modules/vmm/Makefile | 24 | ||||
-rw-r--r-- | sys/net/if_lagg.c | 88 | ||||
-rw-r--r-- | usr.sbin/bhyve/block_if.c | 27 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_ahci.c | 146 |
11 files changed, 272 insertions, 100 deletions
diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8 index 60a6980..99111e2 100644 --- a/sbin/ping6/ping6.8 +++ b/sbin/ping6/ping6.8 @@ -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 diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index 14f689d..9ad285c 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -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); } diff --git a/sys/amd64/vmm/amd/svm_support.S b/sys/amd64/vmm/amd/svm_support.S index 11da759..72327bd 100644 --- a/sys/amd64/vmm/amd/svm_support.S +++ b/sys/amd64/vmm/amd/svm_support.S @@ -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. diff --git a/sys/amd64/vmm/intel/vmx_support.S b/sys/amd64/vmm/intel/vmx_support.S index 840b7e0..84fb5b0 100644 --- a/sys/amd64/vmm/intel/vmx_support.S +++ b/sys/amd64/vmm/intel/vmx_support.S @@ -29,7 +29,7 @@ #include <machine/asmacros.h> -#include "vmx_assym.s" +#include "vmx_assym.h" #ifdef SMP #define LK lock ; diff --git a/sys/conf/files b/sys/conf/files index 13150f4..80755fc 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c index 029d254..6a9c0bf 100644 --- a/sys/fs/autofs/autofs.c +++ b/sys/fs/autofs/autofs.c @@ -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); } } diff --git a/sys/geom/geom_dump.c b/sys/geom/geom_dump.c index 8aaab0f..8ce237f 100644 --- a/sys/geom/geom_dump.c +++ b/sys/geom/geom_dump.c @@ -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 diff --git a/sys/modules/vmm/Makefile b/sys/modules/vmm/Makefile index 5bb31f5..45025a8 100644 --- a/sys/modules/vmm/Makefile +++ b/sys/modules/vmm/Makefile @@ -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> diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 7f7e4b5..5c8b2e1 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -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); diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c index b038228..cbe5ac3 100644 --- a/usr.sbin/bhyve/block_if.c +++ b/usr.sbin/bhyve/block_if.c @@ -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 diff --git a/usr.sbin/bhyve/pci_ahci.c b/usr.sbin/bhyve/pci_ahci.c index 214237d..42aa0b3 100644 --- a/usr.sbin/bhyve/pci_ahci.c +++ b/usr.sbin/bhyve/pci_ahci.c @@ -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 { @@ -360,6 +363,68 @@ ahci_write_reset_fis_d2h(struct ahci_port *p) } 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) { pr->sctl = 0; @@ -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,15 +568,21 @@ 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 */ for (i = 0; i < iovcnt; i++) { @@ -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; @@ -977,6 +1058,16 @@ atapi_read(struct ahci_port *p, int slot, uint8_t *cfis, 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 */ for (i = 0; i < iovcnt; i++) { @@ -1415,9 +1506,14 @@ 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__); @@ -1478,9 +1575,14 @@ 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; |