summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-11-11 11:45:11 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-11-11 11:45:11 +0000
commitc9bed5cc8ec2e46634bc3c9e71c91c68653f2297 (patch)
tree4efedcc6138126a62a29be3c60e0029b158a0b2e /sys/arch
parent852ac968d3a3207a269fa11b52cdbe101e618c72 (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.c12
-rw-r--r--sys/arch/arm64/dev/aplsart.c57
-rw-r--r--sys/arch/arm64/dev/rtkit.c69
-rw-r--r--sys/arch/arm64/dev/rtkit.h3
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);