From 60dbfbaae2817aee3c0f3b31a48ddbd53631d6a2 Mon Sep 17 00:00:00 2001 From: mks Date: Sat, 15 Jan 2000 21:01:04 +0000 Subject: Ensure that DMA mappings are freed in error situations. --- sys/dev/hfa/fore_buffer.c | 6 ++++++ sys/dev/hfa/fore_output.c | 53 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 7 deletions(-) (limited to 'sys/dev/hfa') diff --git a/sys/dev/hfa/fore_buffer.c b/sys/dev/hfa/fore_buffer.c index ff3396d..2c22e42 100644 --- a/sys/dev/hfa/fore_buffer.c +++ b/sys/dev/hfa/fore_buffer.c @@ -407,6 +407,7 @@ fore_buf_supply_1s(fup) * an entry, free up what's been partially built */ if (i != BUF1_SM_ENTSIZE) { + caddr_t cp; /* * Clean up each used descriptor @@ -420,6 +421,8 @@ fore_buf_supply_1s(fup) m = (KBuffer *) ((caddr_t)bhp - BUF1_SM_HOFF); + KB_DATASTART(m, cp, caddr_t); + DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_SM_SIZE, 0); KB_FREEALL(m); } break; @@ -546,6 +549,7 @@ fore_buf_supply_1l(fup) * an entry, free up what's been partially built */ if (i != BUF1_LG_ENTSIZE) { + caddr_t cp; /* * Clean up each used descriptor @@ -558,6 +562,8 @@ fore_buf_supply_1l(fup) m = (KBuffer *) ((caddr_t)bhp - BUF1_LG_HOFF); + KB_DATASTART(m, cp, caddr_t); + DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_LG_SIZE, 0); KB_FREEALL(m); } break; diff --git a/sys/dev/hfa/fore_output.c b/sys/dev/hfa/fore_output.c index e67874c..b0b5436 100644 --- a/sys/dev/hfa/fore_output.c +++ b/sys/dev/hfa/fore_output.c @@ -46,7 +46,8 @@ __RCSID("@(#) $FreeBSD$"); * Local functions */ static KBuffer * fore_xmit_segment __P((Fore_unit *, KBuffer *, - H_xmit_queue *, u_int *, u_int *)); + H_xmit_queue *, int *, int *)); +static void fore_seg_dma_free __P((H_xmit_queue *, KBuffer *, int)); /* @@ -79,7 +80,7 @@ fore_output(cup, cvp, m) H_xmit_queue *hxp; Xmit_queue *cqp; Xmit_descr *xdp; - u_int retry, nsegs, pdulen; + int retry, nsegs, pdulen; int s; #ifdef DIAGNOSTIC @@ -229,8 +230,8 @@ fore_xmit_segment(fup, m, hxp, segp, lenp) Fore_unit *fup; KBuffer *m; H_xmit_queue *hxp; - u_int *segp; - u_int *lenp; + int *segp; + int *lenp; { Xmit_descr *xdp = hxp->hxq_descr; Xmit_seg_descr *xsp; @@ -238,7 +239,7 @@ fore_xmit_segment(fup, m, hxp, segp, lenp) KBuffer *m0, *m1, *mprev; caddr_t cp, bfr; void *dma; - u_int pdulen, nsegs, len, align; + int pdulen, nsegs, len, align; int compressed = 0; m0 = m; @@ -275,6 +276,11 @@ retry: */ if (nsegs >= XMIT_MAX_SEGS) { /* + * First, free already allocated DMA addresses + */ + fore_seg_dma_free(hxp, m0, nsegs); + + /* * Try to compress buffer chain (but only once) */ if (compressed) { @@ -327,7 +333,7 @@ retry: * Have to move some data from following buffer(s) * to word-fill this buffer */ - u_int ncopy = MIN(XMIT_SEG_ALIGN - align, KB_LEN(m1)); + int ncopy = MIN(XMIT_SEG_ALIGN - align, KB_LEN(m1)); if (ncopy) { /* @@ -374,8 +380,8 @@ retry: */ dma = DMA_GET_ADDR(bfr, xsp->xsd_len, XMIT_SEG_ALIGN, 0); if (dma == NULL) { - fup->fu_stats->st_drv.drv_xm_segdma++; + fore_seg_dma_free(hxp, m0, nsegs); KB_FREEALL(m0); return (NULL); } @@ -400,6 +406,7 @@ retry: */ if (pdulen > XMIT_MAX_PDULEN) { fup->fu_stats->st_drv.drv_xm_maxpdu++; + fore_seg_dma_free(hxp, m0, nsegs); KB_FREEALL(m0); return (NULL); } @@ -413,3 +420,35 @@ retry: return (m0); } + +/* + * Free Transmit Segment Queue DMA addresses + * + * Arguments: + * hxp pointer to host transmit queue entry + * m0 pointer to output PDU buffer chain head + * nsegs number of processed transmit segments + * + * Returns: + * none + * + */ +static void +fore_seg_dma_free(hxp, m0, nsegs) + H_xmit_queue *hxp; + KBuffer *m0; + int nsegs; +{ + KBuffer *m = m0; + H_dma *sdmap = hxp->hxq_dma; + caddr_t cp; + int i; + + for (i = 0; i < nsegs; i++) { + KB_DATASTART(m, cp, caddr_t); + DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0); + m = KB_NEXT(m); + sdmap++; + } +} + -- cgit v1.1