bus_dma_dmar_load_ident(9): load identity mapping into the map.
Requested, reviewed and tested by: mav Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D22559
This commit is contained in:
parent
ca293436d1
commit
5c3771d272
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=355138
@ -193,6 +193,8 @@ _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
|
||||
|
||||
#ifdef _KERNEL
|
||||
bool bus_dma_dmar_set_buswide(device_t dev);
|
||||
int bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map,
|
||||
vm_paddr_t start, vm_size_t length, int flags);
|
||||
#endif
|
||||
|
||||
#endif /* !_X86_BUS_DMA_H_ */
|
||||
|
@ -973,3 +973,66 @@ dmar_fini_busdma(struct dmar_unit *unit)
|
||||
taskqueue_free(unit->delayed_taskqueue);
|
||||
unit->delayed_taskqueue = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map1,
|
||||
vm_paddr_t start, vm_size_t length, int flags)
|
||||
{
|
||||
struct bus_dma_tag_common *tc;
|
||||
struct bus_dma_tag_dmar *tag;
|
||||
struct bus_dmamap_dmar *map;
|
||||
struct dmar_ctx *ctx;
|
||||
struct dmar_domain *domain;
|
||||
struct dmar_map_entry *entry;
|
||||
vm_page_t *ma;
|
||||
vm_size_t i;
|
||||
int error;
|
||||
bool waitok;
|
||||
|
||||
MPASS((start & PAGE_MASK) == 0);
|
||||
MPASS((length & PAGE_MASK) == 0);
|
||||
MPASS(length > 0);
|
||||
MPASS(start + length >= start);
|
||||
MPASS((flags & ~(BUS_DMA_NOWAIT | BUS_DMA_NOWRITE)) == 0);
|
||||
|
||||
tc = (struct bus_dma_tag_common *)dmat;
|
||||
if (tc->impl != &bus_dma_dmar_impl)
|
||||
return (0);
|
||||
|
||||
tag = (struct bus_dma_tag_dmar *)dmat;
|
||||
ctx = tag->ctx;
|
||||
domain = ctx->domain;
|
||||
map = (struct bus_dmamap_dmar *)map1;
|
||||
waitok = (flags & BUS_DMA_NOWAIT) != 0;
|
||||
|
||||
entry = dmar_gas_alloc_entry(domain, waitok ? 0 : DMAR_PGF_WAITOK);
|
||||
if (entry == NULL)
|
||||
return (ENOMEM);
|
||||
entry->start = start;
|
||||
entry->end = start + length;
|
||||
ma = malloc(sizeof(vm_page_t) * atop(length), M_TEMP, waitok ?
|
||||
M_WAITOK : M_NOWAIT);
|
||||
if (ma == NULL) {
|
||||
dmar_gas_free_entry(domain, entry);
|
||||
return (ENOMEM);
|
||||
}
|
||||
for (i = 0; i < atop(length); i++) {
|
||||
ma[i] = vm_page_getfake(entry->start + PAGE_SIZE * i,
|
||||
VM_MEMATTR_DEFAULT);
|
||||
}
|
||||
error = dmar_gas_map_region(domain, entry, DMAR_MAP_ENTRY_READ |
|
||||
((flags & BUS_DMA_NOWRITE) ? 0 : DMAR_MAP_ENTRY_WRITE),
|
||||
waitok ? DMAR_GM_CANWAIT : 0, ma);
|
||||
if (error == 0) {
|
||||
DMAR_DOMAIN_LOCK(domain);
|
||||
TAILQ_INSERT_TAIL(&map->map_entries, entry, dmamap_link);
|
||||
entry->flags |= DMAR_MAP_ENTRY_MAP;
|
||||
DMAR_DOMAIN_UNLOCK(domain);
|
||||
} else {
|
||||
dmar_domain_unload_entry(entry, true);
|
||||
}
|
||||
for (i = 0; i < atop(length); i++)
|
||||
vm_page_putfake(ma[i]);
|
||||
free(ma, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ domain_init_rmrr(struct dmar_domain *domain, device_t dev, int bus,
|
||||
}
|
||||
error1 = dmar_gas_map_region(domain, entry,
|
||||
DMAR_MAP_ENTRY_READ | DMAR_MAP_ENTRY_WRITE,
|
||||
DMAR_GM_CANWAIT, ma);
|
||||
DMAR_GM_CANWAIT | DMAR_GM_RMRR, ma);
|
||||
/*
|
||||
* Non-failed RMRR entries are owned by context rb
|
||||
* tree. Get rid of the failed entry, but do not stop
|
||||
|
@ -391,6 +391,7 @@ bool dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno);
|
||||
|
||||
#define DMAR_GM_CANWAIT 0x0001
|
||||
#define DMAR_GM_CANSPLIT 0x0002
|
||||
#define DMAR_GM_RMRR 0x0004
|
||||
|
||||
#define DMAR_PGF_WAITOK 0x0001
|
||||
#define DMAR_PGF_ZERO 0x0002
|
||||
|
@ -543,13 +543,15 @@ dmar_gas_alloc_region(struct dmar_domain *domain, struct dmar_map_entry *entry,
|
||||
*/
|
||||
if (prev != NULL && prev->end > entry->start &&
|
||||
(prev->flags & DMAR_MAP_ENTRY_PLACE) == 0) {
|
||||
if ((prev->flags & DMAR_MAP_ENTRY_RMRR) == 0)
|
||||
if ((flags & DMAR_GM_RMRR) == 0 ||
|
||||
(prev->flags & DMAR_MAP_ENTRY_RMRR) == 0)
|
||||
return (EBUSY);
|
||||
entry->start = prev->end;
|
||||
}
|
||||
if (next->start < entry->end &&
|
||||
(next->flags & DMAR_MAP_ENTRY_PLACE) == 0) {
|
||||
if ((next->flags & DMAR_MAP_ENTRY_RMRR) == 0)
|
||||
if ((flags & DMAR_GM_RMRR) == 0 ||
|
||||
(next->flags & DMAR_MAP_ENTRY_RMRR) == 0)
|
||||
return (EBUSY);
|
||||
entry->end = next->start;
|
||||
}
|
||||
@ -569,7 +571,8 @@ dmar_gas_alloc_region(struct dmar_domain *domain, struct dmar_map_entry *entry,
|
||||
found = dmar_gas_rb_insert(domain, entry);
|
||||
KASSERT(found, ("found RMRR dup %p start %jx end %jx",
|
||||
domain, (uintmax_t)entry->start, (uintmax_t)entry->end));
|
||||
entry->flags = DMAR_MAP_ENTRY_RMRR;
|
||||
if ((flags & DMAR_GM_RMRR) != 0)
|
||||
entry->flags = DMAR_MAP_ENTRY_RMRR;
|
||||
|
||||
#ifdef INVARIANTS
|
||||
struct dmar_map_entry *ip, *in;
|
||||
@ -689,7 +692,7 @@ dmar_gas_map_region(struct dmar_domain *domain, struct dmar_map_entry *entry,
|
||||
|
||||
KASSERT(entry->flags == 0, ("used RMRR entry %p %p %x", domain,
|
||||
entry, entry->flags));
|
||||
KASSERT((flags & ~(DMAR_GM_CANWAIT)) == 0,
|
||||
KASSERT((flags & ~(DMAR_GM_CANWAIT | DMAR_GM_RMRR)) == 0,
|
||||
("invalid flags 0x%x", flags));
|
||||
|
||||
start = entry->start;
|
||||
|
@ -253,4 +253,11 @@ bus_dma_dmar_set_buswide(device_t dev)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
int
|
||||
bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map,
|
||||
vm_paddr_t start, vm_size_t length, int flags)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user