busdma: On systmes that use subr_busdma_bounce, measure deferred time

Measure the total deferred time (from the time we decide to defer until
we try again) for busdma_load requests. On systems that don't ever
defer, there is no performnce change. Add new sysctl
hw.busdma.zoneX.total_deferred_time to report this (in
microseconds).

Normally, deferrals don't happen in modern hardware... Except there's a
lot of buggy hardware that can't cope with memory > 4GB or that can't
cross a 4GB boundary (or even more restrictive values), necessitating
bouncing. This will measure the effect on the I/Os of this deferral.

Sponsored by:		Netflix
Reviewed by:		gallatin, mav
Differential Revision:	https://reviews.freebsd.org/D42550
This commit is contained in:
Warner Losh 2023-11-13 07:23:53 -07:00
parent cb57f50e64
commit 20f8814cd3
4 changed files with 12 additions and 1 deletions

View file

@ -98,6 +98,7 @@ struct bus_dmamap {
struct memdesc mem;
bus_dmamap_callback_t *callback;
void *callback_arg;
__sbintime_t queued_time;
STAILQ_ENTRY(bus_dmamap) links;
u_int flags;
#define DMAMAP_COHERENT (1 << 0)

View file

@ -76,6 +76,7 @@ struct bounce_zone {
#ifdef dmat_domain
int domain;
#endif
sbintime_t total_deferred_time;
bus_size_t alignment;
bus_addr_t lowaddr;
char zoneid[8];
@ -119,6 +120,7 @@ _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
bz = dmat->bounce_zone;
STAILQ_INSERT_TAIL(&bz->bounce_map_waitinglist, map,
links);
map->queued_time = sbinuptime();
mtx_unlock(&bounce_lock);
return (EINPROGRESS);
}
@ -239,7 +241,10 @@ alloc_bounce_zone(bus_dma_tag_t dmat)
"domain", CTLFLAG_RD, &bz->domain, 0,
"memory domain");
#endif
SYSCTL_ADD_SBINTIME_USEC(busdma_sysctl_tree(bz),
SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
"total_deferred_time", CTLFLAG_RD, &bz->total_deferred_time,
"Cumulative time busdma requests are deferred (us)");
if (start_thread) {
if (kproc_create(busdma_thread, NULL, NULL, 0, 0, "busdma") !=
0)
@ -436,6 +441,7 @@ busdma_thread(void *dummy __unused)
STAILQ_HEAD(, bus_dmamap) callbacklist;
bus_dma_tag_t dmat;
struct bus_dmamap *map, *nmap;
struct bounce_zone *bz;
thread_lock(curthread);
sched_class(curthread, PRI_ITHD);
@ -452,8 +458,10 @@ busdma_thread(void *dummy __unused)
STAILQ_FOREACH_SAFE(map, &callbacklist, links, nmap) {
dmat = map->dmat;
bz = dmat->bounce_zone;
dmat_lockfunc(dmat)(dmat_lockfuncarg(dmat),
BUS_DMA_LOCK);
bz->total_deferred_time += (sbinuptime() - map->queued_time);
bus_dmamap_load_mem(map->dmat, map, &map->mem,
map->callback, map->callback_arg, BUS_DMA_WAITOK);
dmat_lockfunc(dmat)(dmat_lockfuncarg(dmat),

View file

@ -95,6 +95,7 @@ struct bus_dmamap {
struct memdesc mem;
bus_dmamap_callback_t *callback;
void *callback_arg;
__sbintime_t queued_time;
STAILQ_ENTRY(bus_dmamap) links;
u_int flags;
#define DMAMAP_COULD_BOUNCE (1 << 0)

View file

@ -90,6 +90,7 @@ struct bus_dmamap {
struct memdesc mem;
bus_dmamap_callback_t *callback;
void *callback_arg;
__sbintime_t queued_time;
STAILQ_ENTRY(bus_dmamap) links;
#ifdef KMSAN
struct memdesc kmsan_mem;