don't allocate a mbuf cluster if we don't need.

This commit is contained in:
yamt 2001-11-27 21:40:55 +00:00
parent 1cd410986d
commit dc2a9f16a0
1 changed files with 40 additions and 25 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cs89x0.c,v 1.1 2001/11/26 19:17:08 yamt Exp $ */ /* $NetBSD: cs89x0.c,v 1.2 2001/11/27 21:40:55 yamt Exp $ */
/* /*
* Copyright 1997 * Copyright 1997
@ -186,7 +186,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cs89x0.c,v 1.1 2001/11/26 19:17:08 yamt Exp $"); __KERNEL_RCSID(0, "$NetBSD: cs89x0.c,v 1.2 2001/11/27 21:40:55 yamt Exp $");
#include "opt_inet.h" #include "opt_inet.h"
@ -354,8 +354,13 @@ cs_attach(sc, enaddr, media, nmedia, defmedia)
* greater than the MTU for an ethernet frame. The code depends on * greater than the MTU for an ethernet frame. The code depends on
* this and to port this to a OS where this was not the case would * this and to port this to a OS where this was not the case would
* not be straightforward. * not be straightforward.
*
* we need 1 byte spare because our
* packet read loop can overrun.
* and we may need pad bytes to align ip header.
*/ */
if (MCLBYTES < ETHER_MAX_LEN) { if (MCLBYTES < ETHER_MAX_LEN + 1 +
ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header)) {
printf("%s: MCLBYTES too small for Ethernet frame\n", printf("%s: MCLBYTES too small for Ethernet frame\n",
sc->sc_dev.dv_xname); sc->sc_dev.dv_xname);
return 1; return 1;
@ -1544,7 +1549,6 @@ cs_process_receive(sc)
struct ifnet *ifp; struct ifnet *ifp;
struct mbuf *m; struct mbuf *m;
int totlen; int totlen;
int len;
u_int16_t *pBuff, *pBuffLimit; u_int16_t *pBuff, *pBuffLimit;
int pad; int pad;
unsigned int frameOffset; unsigned int frameOffset;
@ -1574,6 +1578,15 @@ cs_process_receive(sc)
totlen = CS_READ_PORT(sc, PORT_RXTX_DATA); totlen = CS_READ_PORT(sc, PORT_RXTX_DATA);
} }
if (totlen > ETHER_MAX_LEN) {
printf("%s: invalid packet length\n", sc->sc_dev.dv_xname);
/* skip the received frame */
CS_WRITE_PACKET_PAGE(sc, PKTPG_RX_CFG,
CS_READ_PACKET_PAGE(sc, PKTPG_RX_CFG) | RX_CFG_SKIP);
return;
}
MGETHDR(m, M_DONTWAIT, MT_DATA); MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == 0) { if (m == 0) {
printf("%s: cs_process_receive: unable to allocate mbuf\n", printf("%s: cs_process_receive: unable to allocate mbuf\n",
@ -1593,36 +1606,38 @@ cs_process_receive(sc)
m->m_pkthdr.rcvif = ifp; m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = totlen; m->m_pkthdr.len = totlen;
/* /* number of bytes to align ip header on word boundary for ipintr */
* save processing by always using a mbuf cluster, guarenteed to fit pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
* packet, on i386 NetBSD anyway.
*/
MCLGET(m, M_DONTWAIT);
if (m->m_flags & M_EXT) {
len = MCLBYTES;
} else {
/* couldn't allocate an mbuf cluster */
printf("%s: cs_process_receive: unable to allocate a cluster\n",
sc->sc_dev.dv_xname);
m_freem(m);
/* skip the received frame */ /*
CS_WRITE_PACKET_PAGE(sc, PKTPG_RX_CFG, * alloc mbuf cluster if we need.
CS_READ_PACKET_PAGE(sc, PKTPG_RX_CFG) | RX_CFG_SKIP); * we need 1 byte spare because following
return; * packet read loop can overrun.
*/
if (totlen + pad + 1 > MHLEN) {
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
/* couldn't allocate an mbuf cluster */
printf("%s: cs_process_receive: unable to allocate a cluster\n",
sc->sc_dev.dv_xname);
m_freem(m);
/* skip the received frame */
CS_WRITE_PACKET_PAGE(sc, PKTPG_RX_CFG,
CS_READ_PACKET_PAGE(sc, PKTPG_RX_CFG) | RX_CFG_SKIP);
return;
}
} }
/* align ip header on word boundary for ipintr */ /* align ip header on word boundary for ipintr */
pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
m->m_data += pad; m->m_data += pad;
len -= pad + 1;
m->m_len = len = min(totlen, len); m->m_len = totlen;
pBuff = mtod(m, u_int16_t *); pBuff = mtod(m, u_int16_t *);
/* now read the data from the chip */ /* now read the data from the chip */
if (sc->sc_memorymode) { if (sc->sc_memorymode) {
pBuffLimit = pBuff + (len + 1) / 2; /* don't want to go over */ pBuffLimit = pBuff + (totlen + 1) / 2; /* don't want to go over */
while (pBuff < pBuffLimit) { while (pBuff < pBuffLimit) {
*pBuff++ = CS_READ_PACKET_PAGE(sc, frameOffset); *pBuff++ = CS_READ_PACKET_PAGE(sc, frameOffset);
frameOffset += 2; frameOffset += 2;
@ -1630,7 +1645,7 @@ cs_process_receive(sc)
} }
else { else {
bus_space_read_multi_2(sc->sc_iot, sc->sc_ioh, PORT_RXTX_DATA, bus_space_read_multi_2(sc->sc_iot, sc->sc_ioh, PORT_RXTX_DATA,
pBuff, (len + 1)>>1); pBuff, (totlen + 1)>>1);
} }
cs_ether_input(sc, m); cs_ether_input(sc, m);