summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCan Erkin Acar <canacar@cvs.openbsd.org>2005-09-01 23:35:43 +0000
committerCan Erkin Acar <canacar@cvs.openbsd.org>2005-09-01 23:35:43 +0000
commit586e68e3d6b1ebdbff716df6199b8ef7e3e27a77 (patch)
tree86e653945f8b7f007371c35a7064a85af043e7bc
parent3863d2f8fedb338ab4e682c37fc2be6e6b93a8a8 (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.c99
-rw-r--r--sys/dev/pci/if_san_xilinx.c75
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;
}