summaryrefslogtreecommitdiffstats
path: root/sys/dev/dc/if_dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/dc/if_dc.c')
-rw-r--r--sys/dev/dc/if_dc.c71
1 files changed, 40 insertions, 31 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 4592c29..81cb936 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -96,6 +96,7 @@
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -297,6 +298,11 @@ static driver_t dc_driver = {
};
static devclass_t dc_devclass;
+#ifdef __i386__
+static int dc_quick=1;
+SYSCTL_INT(_hw, OID_AUTO, dc_quick, CTLFLAG_RW,
+ &dc_quick,0,"do not mdevget in dc driver");
+#endif
DRIVER_MODULE(if_dc, cardbus, dc_driver, dc_devclass, 0, 0);
DRIVER_MODULE(if_dc, pci, dc_driver, dc_devclass, 0, 0);
@@ -2206,18 +2212,13 @@ static int dc_list_tx_init(sc)
{
struct dc_chain_data *cd;
struct dc_list_data *ld;
- int i;
+ int i, nexti;
cd = &sc->dc_cdata;
ld = sc->dc_ldata;
for (i = 0; i < DC_TX_LIST_CNT; i++) {
- if (i == (DC_TX_LIST_CNT - 1)) {
- ld->dc_tx_list[i].dc_next =
- vtophys(&ld->dc_tx_list[0]);
- } else {
- ld->dc_tx_list[i].dc_next =
- vtophys(&ld->dc_tx_list[i + 1]);
- }
+ nexti = (i == (DC_TX_LIST_CNT - 1)) ? 0 : i+1 ;
+ ld->dc_tx_list[i].dc_next = vtophys(&ld->dc_tx_list[nexti]);
cd->dc_tx_chain[i] = NULL;
ld->dc_tx_list[i].dc_data = 0;
ld->dc_tx_list[i].dc_ctl = 0;
@@ -2239,7 +2240,7 @@ static int dc_list_rx_init(sc)
{
struct dc_chain_data *cd;
struct dc_list_data *ld;
- int i;
+ int i, nexti;
cd = &sc->dc_cdata;
ld = sc->dc_ldata;
@@ -2247,13 +2248,8 @@ static int dc_list_rx_init(sc)
for (i = 0; i < DC_RX_LIST_CNT; i++) {
if (dc_newbuf(sc, i, NULL) == ENOBUFS)
return(ENOBUFS);
- if (i == (DC_RX_LIST_CNT - 1)) {
- ld->dc_rx_list[i].dc_next =
- vtophys(&ld->dc_rx_list[0]);
- } else {
- ld->dc_rx_list[i].dc_next =
- vtophys(&ld->dc_rx_list[i + 1]);
- }
+ nexti = (i == (DC_RX_LIST_CNT - 1)) ? 0 : i+1 ;
+ ld->dc_rx_list[i].dc_next = vtophys(&ld->dc_rx_list[nexti]);
}
cd->dc_rx_prod = 0;
@@ -2276,16 +2272,11 @@ static int dc_newbuf(sc, i, m)
if (m == NULL) {
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new == NULL) {
- printf("dc%d: no memory for rx list "
- "-- packet dropped!\n", sc->dc_unit);
+ if (m_new == NULL)
return(ENOBUFS);
- }
MCLGET(m_new, M_DONTWAIT);
if (!(m_new->m_flags & M_EXT)) {
- printf("dc%d: no memory for rx list "
- "-- packet dropped!\n", sc->dc_unit);
m_freem(m_new);
return(ENOBUFS);
}
@@ -2479,7 +2470,6 @@ static void dc_rxeof(sc)
i = sc->dc_cdata.dc_rx_prod;
while(!(sc->dc_ldata->dc_rx_list[i].dc_status & DC_RXSTAT_OWN)) {
- struct mbuf *m0 = NULL;
cur_rx = &sc->dc_ldata->dc_rx_list[i];
rxstat = cur_rx->dc_status;
@@ -2524,16 +2514,35 @@ static void dc_rxeof(sc)
/* No errors; receive the packet. */
total_len -= ETHER_CRC_LEN;
+#ifdef __i386__
+ /*
+ * On the x86 we do not have alignment problems, so try to
+ * allocate a new buffer for the receive ring, and pass up
+ * the one where the packet is already, saving the expensive
+ * copy done in m_devget().
+ * If we are on an architecture with alignment problems, or
+ * if the allocation fails, then use m_devget and leave the
+ * existing buffer in the receive ring.
+ */
+ if (dc_quick && dc_newbuf(sc, i, NULL) == 0) {
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = total_len;
+ DC_INC(i, DC_RX_LIST_CNT);
+ } else
+#endif
+ {
+ struct mbuf *m0;
- m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN, ifp,
- NULL);
- dc_newbuf(sc, i, m);
- DC_INC(i, DC_RX_LIST_CNT);
- if (m0 == NULL) {
- ifp->if_ierrors++;
- continue;
+ m0 = m_devget(mtod(m, char *), total_len,
+ ETHER_ALIGN, ifp, NULL);
+ dc_newbuf(sc, i, m);
+ DC_INC(i, DC_RX_LIST_CNT);
+ if (m0 == NULL) {
+ ifp->if_ierrors++;
+ continue;
+ }
+ m = m0;
}
- m = m0;
ifp->if_ipackets++;
eh = mtod(m, struct ether_header *);
OpenPOWER on IntegriCloud