Unmap and free memory when we shutdown rtkit. This fixes an issue where
authorkettenis <kettenis@openbsd.org>
Fri, 11 Nov 2022 11:45:10 +0000 (11:45 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 11 Nov 2022 11:45:10 +0000 (11:45 +0000)
we run out of SART entries after a few suspend/resume cycles.

ok patrick@

sys/arch/arm64/dev/aplns.c
sys/arch/arm64/dev/aplsart.c
sys/arch/arm64/dev/rtkit.c
sys/arch/arm64/dev/rtkit.h

index 38ce224..818d54b 100644 (file)
@@ -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);
@@ -336,6 +338,14 @@ nvme_ans_sart_map(void *cookie, bus_addr_t addr, bus_size_t size)
        return aplsart_map(asc->asc_sart, addr, 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)
index 40ae2e3..fb647aa 100644 (file)
@@ -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;
+}
index ac2d3ae..fc0ecab 100644 (file)
@@ -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>
  *
 #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
index eda7b26..b17b005 100644 (file)
@@ -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);