Add hw.dmar.batch_coalesce tunable/sysctl, which specifies rate at

which queued invalidation completion interrupt is requested with
regard to the queued invalidation requests.  In other words, setting
the value of the knob to N requests completion interrupt after N items
are processed.  Existing behaviour is restored by setting
hw.dmar.batch_coalesce=1.

The knob significantly decreases the DMAR qi interrupt rate at the
cost of slightly longer DMAR map entries recycling.

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Konstantin Belousov 2016-04-17 10:56:56 +00:00
parent 916d57dfc5
commit e164cafc69
3 changed files with 20 additions and 2 deletions

View File

@ -711,6 +711,18 @@ dmar_domain_unload_entry(struct dmar_map_entry *entry, bool free)
}
}
static struct dmar_qi_genseq *
dmar_domain_unload_gseq(struct dmar_domain *domain,
struct dmar_map_entry *entry, struct dmar_qi_genseq *gseq)
{
if (TAILQ_NEXT(entry, dmamap_link) != NULL)
return (NULL);
if (domain->batch_no++ % dmar_batch_coalesce != 0)
return (NULL);
return (gseq);
}
void
dmar_domain_unload(struct dmar_domain *domain,
struct dmar_map_entries_tailq *entries, bool cansleep)
@ -744,8 +756,8 @@ dmar_domain_unload(struct dmar_domain *domain,
entry->gseq.gen = 0;
entry->gseq.seq = 0;
dmar_qi_invalidate_locked(domain, entry->start, entry->end -
entry->start, TAILQ_NEXT(entry, dmamap_link) == NULL ?
&gseq : NULL);
entry->start, dmar_domain_unload_gseq(domain, entry,
&gseq));
}
TAILQ_FOREACH_SAFE(entry, entries, dmamap_link, entry1) {
entry->gseq = gseq;

View File

@ -114,6 +114,7 @@ struct dmar_domain {
unload */
struct dmar_map_entry *first_place, *last_place; /* (d) */
struct task unload_task; /* (c) */
u_int batch_no;
};
struct dmar_ctx {
@ -378,6 +379,7 @@ extern dmar_haddr_t dmar_high;
extern int haw;
extern int dmar_tbl_pagecnt;
extern int dmar_match_verbose;
extern int dmar_batch_coalesce;
extern int dmar_check_free;
static inline uint32_t

View File

@ -618,6 +618,7 @@ dmar_barrier_exit(struct dmar_unit *dmar, u_int barrier_id)
}
int dmar_match_verbose;
int dmar_batch_coalesce = 100;
static SYSCTL_NODE(_hw, OID_AUTO, dmar, CTLFLAG_RD, NULL, "");
SYSCTL_INT(_hw_dmar, OID_AUTO, tbl_pagecnt, CTLFLAG_RD,
@ -626,6 +627,9 @@ SYSCTL_INT(_hw_dmar, OID_AUTO, tbl_pagecnt, CTLFLAG_RD,
SYSCTL_INT(_hw_dmar, OID_AUTO, match_verbose, CTLFLAG_RWTUN,
&dmar_match_verbose, 0,
"Verbose matching of the PCI devices to DMAR paths");
SYSCTL_INT(_hw_dmar, OID_AUTO, batch_coalesce, CTLFLAG_RWTUN,
&dmar_batch_coalesce, 0,
"Number of qi batches between interrupt");
#ifdef INVARIANTS
int dmar_check_free;
SYSCTL_INT(_hw_dmar, OID_AUTO, check_free, CTLFLAG_RWTUN,