summaryrefslogtreecommitdiffstats
path: root/sys/dev/hfa
diff options
context:
space:
mode:
authormks <mks@FreeBSD.org>2000-01-15 21:01:04 +0000
committermks <mks@FreeBSD.org>2000-01-15 21:01:04 +0000
commit60dbfbaae2817aee3c0f3b31a48ddbd53631d6a2 (patch)
tree4bb7c146b4a1b175d968ccee0e9bc8b67e5eaa9d /sys/dev/hfa
parentc7afe93038634ff5f2d102d5c21fec1a1e0fe787 (diff)
downloadFreeBSD-src-60dbfbaae2817aee3c0f3b31a48ddbd53631d6a2.zip
FreeBSD-src-60dbfbaae2817aee3c0f3b31a48ddbd53631d6a2.tar.gz
Ensure that DMA mappings are freed in error situations.
Diffstat (limited to 'sys/dev/hfa')
-rw-r--r--sys/dev/hfa/fore_buffer.c6
-rw-r--r--sys/dev/hfa/fore_output.c53
2 files changed, 52 insertions, 7 deletions
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++;
+ }
+}
+
OpenPOWER on IntegriCloud