diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-11-11 11:45:11 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-11-11 11:45:11 +0000 |
commit | c9bed5cc8ec2e46634bc3c9e71c91c68653f2297 (patch) | |
tree | 4efedcc6138126a62a29be3c60e0029b158a0b2e /sys/arch | |
parent | 852ac968d3a3207a269fa11b52cdbe101e618c72 (diff) |
Unmap and free memory when we shutdown rtkit. This fixes an issue where
we run out of SART entries after a few suspend/resume cycles.
ok patrick@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/arm64/dev/aplns.c | 12 | ||||
-rw-r--r-- | sys/arch/arm64/dev/aplsart.c | 57 | ||||
-rw-r--r-- | sys/arch/arm64/dev/rtkit.c | 69 | ||||
-rw-r--r-- | sys/arch/arm64/dev/rtkit.h | 3 |
4 files changed, 115 insertions, 26 deletions
diff --git a/sys/arch/arm64/dev/aplns.c b/sys/arch/arm64/dev/aplns.c index 38ce2246c79..818d54b707d 100644 --- a/sys/arch/arm64/dev/aplns.c +++ b/sys/arch/arm64/dev/aplns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplns.c,v 1.14 2022/11/09 19:18:11 kettenis Exp $ */ +/* $OpenBSD: aplns.c,v 1.15 2022/11/11 11:45:10 kettenis Exp $ */ /* * Copyright (c) 2014, 2021 David Gwynne <dlg@openbsd.org> * @@ -93,6 +93,7 @@ struct cfdriver aplns_cd = { }; int nvme_ans_sart_map(void *, bus_addr_t, bus_size_t); +int nvme_ans_sart_unmap(void *, bus_addr_t, bus_size_t); int aplns_match(struct device *parent, void *match, void *aux) @@ -213,6 +214,7 @@ nvme_ans_attach(struct device *parent, struct device *self, void *aux) asc->asc_rtkit.rk_cookie = asc; asc->asc_rtkit.rk_dmat = faa->fa_dmat; asc->asc_rtkit.rk_map = nvme_ans_sart_map; + asc->asc_rtkit.rk_unmap = nvme_ans_sart_unmap; asc->asc_rtkit_state = rtkit_init(faa->fa_node, NULL, 0, &asc->asc_rtkit); @@ -337,6 +339,14 @@ nvme_ans_sart_map(void *cookie, bus_addr_t addr, bus_size_t size) } int +nvme_ans_sart_unmap(void *cookie, bus_addr_t addr, bus_size_t size) +{ + struct nvme_ans_softc *asc = cookie; + + return aplsart_unmap(asc->asc_sart, addr, size); +} + +int nvme_ans_q_alloc(struct nvme_softc *sc, struct nvme_queue *q) { diff --git a/sys/arch/arm64/dev/aplsart.c b/sys/arch/arm64/dev/aplsart.c index 40ae2e3b4a3..fb647aaeb61 100644 --- a/sys/arch/arm64/dev/aplsart.c +++ b/sys/arch/arm64/dev/aplsart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplsart.c,v 1.3 2022/11/10 14:15:15 kettenis Exp $ */ +/* $OpenBSD: aplsart.c,v 1.4 2022/11/11 11:45:10 kettenis Exp $ */ /* * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org> * @@ -188,3 +188,58 @@ aplsart_map(uint32_t phandle, bus_addr_t addr, bus_size_t size) return ENXIO; } + +int +aplsart2_unmap(struct aplsart_softc *sc, bus_addr_t addr, bus_size_t size) +{ + int i; + + for (i = 0; i < SART_NUM_ENTRIES; i++) { + if (HREAD4(sc, SART2_ADDR(i)) != (addr >> SART_ADDR_SHIFT)) + continue; + + HWRITE4(sc, SART2_ADDR(i), 0); + HWRITE4(sc, SART2_CONFIG(i), 0); + return 0; + } + + return ENOENT; +} + +int +aplsart3_unmap(struct aplsart_softc *sc, bus_addr_t addr, bus_size_t size) +{ + int i; + + for (i = 0; i < SART_NUM_ENTRIES; i++) { + if (HREAD4(sc, SART3_ADDR(i)) != (addr >> SART_ADDR_SHIFT)) + continue; + + HWRITE4(sc, SART3_ADDR(i), 0); + HWRITE4(sc, SART3_SIZE(i), 0); + HWRITE4(sc, SART3_CONFIG(i), 0); + return 0; + } + + return ENOENT; +} + +int +aplsart_unmap(uint32_t phandle, bus_addr_t addr, bus_size_t size) +{ + struct aplsart_softc *sc; + int i; + + for (i = 0; i < aplsart_cd.cd_ndevs; i++) { + sc = (struct aplsart_softc *)aplsart_cd.cd_devs[i]; + + if (sc->sc_phandle == phandle) { + if (sc->sc_version == 2) + return aplsart2_unmap(sc, addr, size); + else + return aplsart3_unmap(sc, addr, size); + } + } + + return ENXIO; +} diff --git a/sys/arch/arm64/dev/rtkit.c b/sys/arch/arm64/dev/rtkit.c index ac2d3ae2942..fc0ecab9542 100644 --- a/sys/arch/arm64/dev/rtkit.c +++ b/sys/arch/arm64/dev/rtkit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtkit.c,v 1.8 2022/11/09 19:18:11 kettenis Exp $ */ +/* $OpenBSD: rtkit.c,v 1.9 2022/11/11 11:45:10 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> * @@ -78,6 +78,12 @@ #define RTKIT_MINVER 11 #define RTKIT_MAXVER 12 +struct rtkit_dmamem { + bus_dmamap_t rdm_map; + bus_dma_segment_t rdm_seg; + size_t rdm_size; +}; + struct rtkit_state { struct mbox_channel *mc; struct rtkit *rk; @@ -86,6 +92,8 @@ struct rtkit_state { uint64_t epmap; void (*callback[32])(void *, uint64_t); void *arg[32]; + struct rtkit_dmamem dmamem[32]; + int ndmamem; }; int @@ -115,12 +123,16 @@ rtkit_send(struct mbox_channel *mc, uint32_t endpoint, } bus_addr_t -rtkit_alloc(struct rtkit *rk, bus_size_t size) +rtkit_alloc(struct rtkit_state *state, bus_size_t size) { + struct rtkit *rk = state->rk; bus_dma_segment_t seg; bus_dmamap_t map; int nsegs; + if (state->ndmamem >= nitems(state->dmamem)) + return ENOMEM; + if (bus_dmamem_alloc(rk->rk_dmat, size, 16384, 0, &seg, 1, &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO)) return (bus_addr_t)-1; @@ -138,6 +150,20 @@ rtkit_alloc(struct rtkit *rk, bus_size_t size) return (bus_addr_t)-1; } + if (rk->rk_map) { + if (rk->rk_map(rk->rk_cookie, seg.ds_addr, seg.ds_len)) { + bus_dmamap_unload(rk->rk_dmat, map); + bus_dmamap_destroy(rk->rk_dmat, map); + bus_dmamem_free(rk->rk_dmat, &seg, 1); + return (bus_addr_t)-1; + } + } + + state->dmamem[state->ndmamem].rdm_map = map; + state->dmamem[state->ndmamem].rdm_seg = seg; + state->dmamem[state->ndmamem].rdm_size = size; + state->ndmamem++; + return seg.ds_addr; } @@ -249,15 +275,9 @@ rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) break; if (rk) { - addr = rtkit_alloc(rk, size << PAGE_SHIFT); + addr = rtkit_alloc(state, size << PAGE_SHIFT); if (addr == (bus_addr_t)-1) return ENOMEM; - if (rk->rk_map) { - error = rk->rk_map(rk->rk_cookie, addr, - size << PAGE_SHIFT); - if (error) - return error; - } } error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, @@ -291,15 +311,9 @@ rtkit_handle_syslog(struct rtkit_state *state, struct aplmbox_msg *msg) break; if (rk) { - addr = rtkit_alloc(rk, size << PAGE_SHIFT); + addr = rtkit_alloc(state, size << PAGE_SHIFT); if (addr == (bus_addr_t)-1) return ENOMEM; - if (rk->rk_map) { - error = rk->rk_map(rk->rk_cookie, addr, - size << PAGE_SHIFT); - if (error) - return error; - } } error = rtkit_send(mc, RTKIT_EP_SYSLOG, RTKIT_BUFFER_REQUEST, @@ -341,15 +355,9 @@ rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) break; if (rk) { - addr = rtkit_alloc(rk, size << PAGE_SHIFT); + addr = rtkit_alloc(state, size << PAGE_SHIFT); if (addr == (bus_addr_t)-1) return ENOMEM; - if (rk->rk_map) { - error = rk->rk_map(rk->rk_cookie, addr, - size << PAGE_SHIFT); - if (error) - return error; - } } error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, @@ -479,6 +487,8 @@ void rtkit_shutdown(struct rtkit_state *state) { struct mbox_channel *mc = state->mc; + struct rtkit *rk = state->rk; + int i; if (state->ap_pwrstate != RTKIT_MGMT_PWR_STATE_QUIESCED) rtkit_set_ap_pwrstate(state, RTKIT_MGMT_PWR_STATE_QUIESCED); @@ -492,6 +502,19 @@ rtkit_shutdown(struct rtkit_state *state) KASSERT(state->iop_pwrstate == RTKIT_MGMT_PWR_STATE_SLEEP); KASSERT(state->ap_pwrstate == RTKIT_MGMT_PWR_STATE_QUIESCED); state->epmap = 0; + + /* Clean up our memory allocations. */ + for (i = 0; i < state->ndmamem; i++) { + if (rk->rk_unmap) { + rk->rk_unmap(rk->rk_cookie, + state->dmamem[i].rdm_seg.ds_addr, + state->dmamem[i].rdm_seg.ds_len); + } + bus_dmamap_unload(rk->rk_dmat, state->dmamem[i].rdm_map); + bus_dmamap_destroy(rk->rk_dmat, state->dmamem[i].rdm_map); + bus_dmamem_free(rk->rk_dmat, &state->dmamem[i].rdm_seg, 1); + } + state->ndmamem = 0; } int diff --git a/sys/arch/arm64/dev/rtkit.h b/sys/arch/arm64/dev/rtkit.h index eda7b266894..b17b005807c 100644 --- a/sys/arch/arm64/dev/rtkit.h +++ b/sys/arch/arm64/dev/rtkit.h @@ -10,6 +10,7 @@ struct rtkit { void *rk_cookie; bus_dma_tag_t rk_dmat; int (*rk_map)(void *, bus_addr_t, bus_size_t); + int (*rk_unmap)(void *, bus_addr_t, bus_size_t); }; #define RK_WAKEUP 0x00000001 @@ -25,4 +26,4 @@ int rtkit_send_endpoint(struct rtkit_state *, uint32_t, uint64_t); int aplrtk_start(uint32_t); int aplsart_map(uint32_t, bus_addr_t, bus_size_t); - +int aplsart_unmap(uint32_t, bus_addr_t, bus_size_t); |