diff options
author | Can Erkin Acar <canacar@cvs.openbsd.org> | 2005-09-01 23:35:43 +0000 |
---|---|---|
committer | Can Erkin Acar <canacar@cvs.openbsd.org> | 2005-09-01 23:35:43 +0000 |
commit | 586e68e3d6b1ebdbff716df6199b8ef7e3e27a77 (patch) | |
tree | 86e653945f8b7f007371c35a7064a85af043e7bc | |
parent | 3863d2f8fedb338ab4e682c37fc2be6e6b93a8a8 (diff) |
Make sure the packets are aligned for dma while copying,
cleanup extra alignment code, and check lengths properly while copying.
tested by Greg Mortensen thevision at pobox com
ok deraadt@
-rw-r--r-- | sys/dev/pci/if_san_common.c | 99 | ||||
-rw-r--r-- | sys/dev/pci/if_san_xilinx.c | 75 |
2 files changed, 77 insertions, 97 deletions
diff --git a/sys/dev/pci/if_san_common.c b/sys/dev/pci/if_san_common.c index e641dc05bd1..dbbff25a4a4 100644 --- a/sys/dev/pci/if_san_common.c +++ b/sys/dev/pci/if_san_common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_san_common.c,v 1.8 2005/04/05 20:11:10 canacar Exp $ */ +/* $OpenBSD: if_san_common.c,v 1.9 2005/09/01 23:35:42 canacar Exp $ */ /*- * Copyright (c) 2001-2004 Sangoma Technologies (SAN) @@ -383,56 +383,91 @@ sdla_isr(void *pcard) return (1); } -// XXX check usage, why is len not used ??? struct mbuf* wan_mbuf_alloc(int len) { struct mbuf *m; - if (len) - MGETHDR(m, M_DONTWAIT, MT_DATA); - else - MGET(m, M_DONTWAIT, MT_DATA); + /* XXX handle len > MCLBYTES */ + if (len <= 0 || len > MCLBYTES) + return (NULL); - if (m != NULL) { - if (m->m_flags & M_PKTHDR) - m->m_pkthdr.len = 0; + MGETHDR(m, M_DONTWAIT, MT_DATA); - m->m_len = 0; - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - return NULL; - } + if (m == NULL || len < MHLEN) + return (m); - m->m_data += 16; + m->m_pkthdr.len = 0; + m->m_len = 0; + MCLGET(m, M_DONTWAIT); + + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return (NULL); } + return (m); } -// XXX check len while copy? int wan_mbuf_to_buffer(struct mbuf **m_org) { - struct mbuf *m = *m_org, *new = NULL; + struct mbuf *m, *m0, *tmp; + char *buffer; + size_t len; + + if (m_org == NULL || *m_org == NULL) + return (EINVAL); + + m0 = *m_org; +#if 0 + /* no need to copy if it is a single, properly aligned mbuf */ + if (m0->m_next == NULL && (mtod(m0, u_int32_t) & 0x03) == 0) + return (0); +#endif + MGET(m, M_DONTWAIT, MT_DATA); if (m == NULL) - return EINVAL; + return (ENOMEM); - new = wan_mbuf_alloc(0); - if (new){ - struct mbuf *tmp = m; - char *buffer = new->m_data; + MCLGET(m, M_DONTWAIT); - for( ; tmp; tmp = tmp->m_next) { - bcopy(mtod(tmp, caddr_t), buffer, tmp->m_len); - buffer += tmp->m_len; - new->m_len += tmp->m_len; - } + if ((m->m_flags & M_EXT) == 0) { m_freem(m); - *m_org = new; - return 0; + return (ENOMEM); } - return EINVAL; -} + m->m_len = 0; + + /* XXX handle larger packets? */ + len = MCLBYTES ; + buffer = mtod(m, caddr_t); + + len -= 16; + buffer += 16; + + /* make sure the buffer is aligned to an 8-byte boundary */ + if (mtod(m, u_int32_t) & 0x03) { + unsigned int inc = 4 - (mtod(m, u_int32_t) & 0x03); + buffer += inc; + len -= inc; + } + + m->m_data = buffer; + + for (tmp = m0; tmp; tmp = tmp->m_next) { + if (tmp->m_len > len) { + m_freem(m); + return (EINVAL); + } + bcopy(mtod(tmp, caddr_t), buffer, tmp->m_len); + buffer += tmp->m_len; + m->m_len += tmp->m_len; + len -= tmp->m_len; + } + + m_freem(m0); + *m_org = m; + + return (0); +} diff --git a/sys/dev/pci/if_san_xilinx.c b/sys/dev/pci/if_san_xilinx.c index b8a3795fb51..3a821291acd 100644 --- a/sys/dev/pci/if_san_xilinx.c +++ b/sys/dev/pci/if_san_xilinx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_san_xilinx.c,v 1.10 2005/04/25 17:55:51 brad Exp $ */ +/* $OpenBSD: if_san_xilinx.c,v 1.11 2005/09/01 23:35:42 canacar Exp $ */ /*- * Copyright (c) 2001-2004 Sangoma Technologies (SAN) @@ -164,11 +164,6 @@ typedef struct { void *prot_ch; wan_trace_t trace_info; - - u_int8_t tx_dma_status; - bus_dma_segment_t tx_dma_seg; - int tx_dma_rseg; - caddr_t tx_dma_vaddr; }xilinx_softc_t; #define WAN_IFP_TO_SOFTC(ifp) (xilinx_softc_t *)((ifp)->if_softc) @@ -572,14 +567,6 @@ wan_xilinx_down(struct ifnet *ifp) aft_init_requeue_free_m(sc, m); sc->rx_dma_mbuf = NULL; } - if (bit_test((u_int8_t *)&sc->tx_dma_status, TX_DMA_BUF_INIT)){ - bus_dma_tag_t dmat; - - sdla_getcfg(card->hw, SDLA_DMATAG, &dmat); - bus_dmamem_unmap(dmat, sc->tx_dma_vaddr, sc->dma_mtu); - bus_dmamem_free(dmat, &sc->tx_dma_seg, sc->tx_dma_rseg); - bit_clear((u_int8_t *)&sc->tx_dma_status, TX_DMA_BUF_INIT); - } /* If there is something in rx_complete_list, then ** move evething to rx_free_list. */ @@ -1852,58 +1839,16 @@ xilinx_dma_tx(sdla_t *card, xilinx_softc_t *sc) } if (mtod(m, u_int32_t) & 0x03) { - if (!bit_test((u_int8_t *)&sc->tx_dma_status, - TX_DMA_BUF_INIT)) { - bus_dma_tag_t dmat; - int err; - - sdla_getcfg(card->hw, SDLA_DMATAG, &dmat); - err = bus_dmamem_alloc( - dmat, - sc->dma_mtu, - PAGE_SIZE, - 0, - &sc->tx_dma_seg, - 1, - &sc->tx_dma_rseg, - BUS_DMA_NOWAIT); - if (err) { - log(LOG_INFO, - "%s: Failed allocate DMA buffer!\n", - sc->if_name); - m_freem(m); - bit_clear((u_int8_t *)&sc->dma_status, - TX_BUSY); - return (EINVAL); - } - err = bus_dmamem_map( - dmat, - &sc->tx_dma_seg, - sc->tx_dma_rseg, - sc->dma_mtu, - (caddr_t*)&sc->tx_dma_vaddr, - BUS_DMA_NOWAIT); - if (err) { - log(LOG_INFO, - "%s: Failed to map DMA buffer!\n", - sc->if_name); - bus_dmamem_free( - dmat, - &sc->tx_dma_seg, - sc->tx_dma_rseg); - m_freem(m); - bit_clear((u_int8_t *)&sc->dma_status, - TX_BUSY); - return (EINVAL); - } - bit_set((u_int8_t *)&sc->tx_dma_status, - TX_DMA_BUF_INIT); - } - memcpy(sc->tx_dma_vaddr, mtod(m, caddr_t), m->m_len); - sc->tx_dma_addr = kvtop(sc->tx_dma_vaddr); - } else { - sc->tx_dma_addr = kvtop(mtod(m, caddr_t)); + /* The mbuf should already be aligned */ + log(LOG_INFO, "%s: TX packed not aligned " + "(%s:%d)!\n", sc->if_name, + MAX_XILINX_TX_DMA_SIZE, __FUNCTION__, __LINE__); + m_freem(m); + bit_clear((u_int8_t *)&sc->dma_status, TX_BUSY); + return (EINVAL); } + + sc->tx_dma_addr = kvtop(mtod(m, caddr_t)); sc->tx_dma_len = len; } |