Fix minor bug that would cause the packet statistics updates to stop

working under extremely rare circumstances. Also added some additional
comments..
This commit is contained in:
David Greenman 1995-12-01 22:41:56 +00:00
parent d7b3176278
commit dfe61cf102
2 changed files with 150 additions and 48 deletions

View File

@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: if_fxp.c,v 1.1 1995/11/28 23:55:20 davidg Exp $
*/
/*
@ -74,18 +74,18 @@
#include <net/bpfdesc.h>
#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <machine/clock.h>
#include <machine/pmap.h>
#include <vm/vm.h> /* for vtophys */
#include <vm/vm_param.h> /* for vtophys */
#include <machine/pmap.h> /* for vtophys */
#include <machine/clock.h> /* for DELAY */
#include <pci/pcivar.h>
#include <pci/if_fxpreg.h>
struct fxp_softc {
struct arpcom arpcom;
caddr_t bpf;
struct fxp_csr *csr;
struct arpcom arpcom; /* per-interface network data */
caddr_t bpf; /* BPF token */
struct fxp_csr *csr; /* control/status registers */
struct fxp_cb_tx *cbl_base; /* base of TxCB list */
struct fxp_cb_tx *cbl_first; /* first active TxCB in list */
struct fxp_cb_tx *cbl_last; /* last active TxCB in list */
@ -181,6 +181,10 @@ DATA_SET(pcidevice_set, fxp_device);
*/
#define FXP_NRFABUFS 32
/*
* Wait for the previous command to be accepted (but not necessarily
* completed).
*/
static inline void
fxp_scb_wait(csr)
struct fxp_csr *csr;
@ -190,6 +194,9 @@ fxp_scb_wait(csr)
while ((csr->scb_command & FXP_SCB_COMMAND_MASK) && --i);
}
/*
* Return identification string if this is device is ours.
*/
static char *
fxp_probe(config_id, device_id)
pcici_t config_id;
@ -222,6 +229,9 @@ fxp_attach(config_id, unit)
s = splimp();
/*
* Map control/status registers.
*/
if (!pci_map_mem(config_id, FXP_PCI_MMBA,
(vm_offset_t *)&sc->csr, &pbase)) {
printf("fxp%d: couldn't map memory\n", unit);
@ -229,11 +239,14 @@ fxp_attach(config_id, unit)
}
/*
* Now that the CSR is mapped, issue a software reset.
* Issue a software reset.
*/
sc->csr->port = 0;
DELAY(10);
/*
* Allocate our interrupt.
*/
if (!pci_map_int(config_id, fxp_intr, sc, &net_imask)) {
printf("fxp%d: couldn't map interrupt\n", unit);
goto fail;
@ -249,6 +262,9 @@ fxp_attach(config_id, unit)
goto malloc_fail;
bzero(sc->fxp_stats, sizeof(struct fxp_stats));
/*
* Pre-allocate our receive buffers.
*/
for (i = 0; i < FXP_NRFABUFS; i++) {
if (fxp_add_rfabuf(sc, NULL) != 0) {
goto malloc_fail;
@ -270,6 +286,9 @@ fxp_attach(config_id, unit)
printf("fxp%d: Ethernet address %s\n", unit,
ether_sprintf(sc->arpcom.ac_enaddr));
/*
* Attach the interface.
*/
if_attach(ifp);
#if NBPFILTER > 0
bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
@ -409,6 +428,9 @@ fxp_start(ifp)
ifp->if_flags |= IFF_OACTIVE;
return;
}
/*
* Grab a packet to transmit.
*/
IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, mb_head);
if (mb_head == NULL) {
/*
@ -417,6 +439,9 @@ fxp_start(ifp)
return;
}
/*
* Get pointer to next available (unused) descriptor.
*/
txp = sc->cbl_last->next;
/*
@ -550,12 +575,19 @@ fxp_intr(arg)
struct fxp_rfa *rfa;
rcvloop:
m = sc->rfa_headm;
rfa = (struct fxp_rfa *)(mtod(m, u_long) & ~(MCLBYTES - 1));
rfa = (struct fxp_rfa *)m->m_ext.ext_buf;
if (rfa->rfa_status & FXP_RFA_STATUS_C) {
/*
* Remove first packet from the chain.
*/
sc->rfa_headm = m->m_next;
m->m_next = NULL;
/*
* Add a new buffer to the receive chain. If this
* fails, the old buffer is recycled instead.
*/
if (fxp_add_rfabuf(sc, m) == 0) {
struct ether_header *eh;
u_short total_len;
@ -589,8 +621,7 @@ fxp_intr(arg)
ifp->if_ierrors++;
fxp_scb_wait(csr);
csr->scb_general = vtophys(mtod(sc->rfa_headm, u_long) &
~(MCLBYTES - 1));
csr->scb_general = vtophys(sc->rfa_headm->m_ext.ext_buf);
csr->scb_command = FXP_SCB_COMMAND_RU_START;
}
}
@ -599,6 +630,17 @@ fxp_intr(arg)
return found;
}
/*
* Update packet in/out/collision statistics. The i82557 doesn't
* allow you to access these counters without doing a fairly
* expensive DMA to get _all_ of the statistics it maintains, so
* we do this operation here only once per second. The statistics
* counters in the kernel are updated from the previous dump-stats
* DMA and then a new dump-stats DMA is started. The on-chip
* counters are zeroed when the DMA completes. If we can't start
* the DMA immediately, we don't wait - we just prepare to read
* them again next time.
*/
void
fxp_stats_update(arg)
void *arg;
@ -616,19 +658,24 @@ fxp_stats_update(arg)
* around. Make sure we don't count the stats twice
* however.
*/
if (sc->csr->scb_command & FXP_SCB_COMMAND_MASK) {
if ((sc->csr->scb_command & FXP_SCB_COMMAND_MASK) == 0) {
/*
* Start another stats dump. By waiting for it to be
* accepted, we avoid having to do splhigh locking when
* writing scb_command in other parts of the driver.
*/
sc->csr->scb_command = FXP_SCB_COMMAND_CU_DUMPRESET;
fxp_scb_wait(sc);
} else {
/*
* A previous command is still waiting to be accepted.
* Just zero our copy of the stats and wait for the
* next timer event to pdate them.
*/
sp->tx_good = 0;
sp->tx_total_collisions = 0;
sp->rx_good = 0;
return;
}
/*
* Start another stats dump. By waiting for it to be accepted,
* we avoid having to do splhigh locking when writing scb_command
* in other parts of the driver.
*/
sc->csr->scb_command = FXP_SCB_COMMAND_CU_DUMPRESET;
fxp_scb_wait(sc);
/*
* Schedule another timeout one second from now.
*/
@ -830,7 +877,7 @@ fxp_init(unit)
* Initialize receiver buffer area - RFA.
*/
fxp_scb_wait(csr);
csr->scb_general = vtophys(mtod(sc->rfa_headm, u_long) & ~(MCLBYTES - 1));
csr->scb_general = vtophys(sc->rfa_headm->m_ext.ext_buf);
csr->scb_command = FXP_SCB_COMMAND_RU_START;
ifp->if_flags |= IFF_RUNNING;
@ -879,8 +926,12 @@ fxp_add_rfabuf(sc, oldm)
rfa->actual_size = 0;
rfa->size = MCLBYTES - sizeof(struct fxp_rfa);
m->m_data += sizeof(struct fxp_rfa);
/*
* If there are other buffers already on the list, attach this
* one to the end by fixing up the tail to point to this one.
*/
if (sc->rfa_headm != NULL) {
p_rfa = (struct fxp_rfa *) (mtod(sc->rfa_tailm, u_long) & ~(MCLBYTES - 1));
p_rfa = (struct fxp_rfa *) sc->rfa_tailm->m_ext.ext_buf;
sc->rfa_tailm->m_next = m;
p_rfa->link_addr = vtophys(rfa);
p_rfa->rfa_control &= ~FXP_RFA_CONTROL_EL;
@ -889,7 +940,7 @@ fxp_add_rfabuf(sc, oldm)
}
sc->rfa_tailm = m;
return m == oldm ? 1 : 0;
return (m == oldm);
}
static int

View File

@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: if_fxp.c,v 1.1 1995/11/28 23:55:20 davidg Exp $
*/
/*
@ -74,18 +74,18 @@
#include <net/bpfdesc.h>
#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <machine/clock.h>
#include <machine/pmap.h>
#include <vm/vm.h> /* for vtophys */
#include <vm/vm_param.h> /* for vtophys */
#include <machine/pmap.h> /* for vtophys */
#include <machine/clock.h> /* for DELAY */
#include <pci/pcivar.h>
#include <pci/if_fxpreg.h>
struct fxp_softc {
struct arpcom arpcom;
caddr_t bpf;
struct fxp_csr *csr;
struct arpcom arpcom; /* per-interface network data */
caddr_t bpf; /* BPF token */
struct fxp_csr *csr; /* control/status registers */
struct fxp_cb_tx *cbl_base; /* base of TxCB list */
struct fxp_cb_tx *cbl_first; /* first active TxCB in list */
struct fxp_cb_tx *cbl_last; /* last active TxCB in list */
@ -181,6 +181,10 @@ DATA_SET(pcidevice_set, fxp_device);
*/
#define FXP_NRFABUFS 32
/*
* Wait for the previous command to be accepted (but not necessarily
* completed).
*/
static inline void
fxp_scb_wait(csr)
struct fxp_csr *csr;
@ -190,6 +194,9 @@ fxp_scb_wait(csr)
while ((csr->scb_command & FXP_SCB_COMMAND_MASK) && --i);
}
/*
* Return identification string if this is device is ours.
*/
static char *
fxp_probe(config_id, device_id)
pcici_t config_id;
@ -222,6 +229,9 @@ fxp_attach(config_id, unit)
s = splimp();
/*
* Map control/status registers.
*/
if (!pci_map_mem(config_id, FXP_PCI_MMBA,
(vm_offset_t *)&sc->csr, &pbase)) {
printf("fxp%d: couldn't map memory\n", unit);
@ -229,11 +239,14 @@ fxp_attach(config_id, unit)
}
/*
* Now that the CSR is mapped, issue a software reset.
* Issue a software reset.
*/
sc->csr->port = 0;
DELAY(10);
/*
* Allocate our interrupt.
*/
if (!pci_map_int(config_id, fxp_intr, sc, &net_imask)) {
printf("fxp%d: couldn't map interrupt\n", unit);
goto fail;
@ -249,6 +262,9 @@ fxp_attach(config_id, unit)
goto malloc_fail;
bzero(sc->fxp_stats, sizeof(struct fxp_stats));
/*
* Pre-allocate our receive buffers.
*/
for (i = 0; i < FXP_NRFABUFS; i++) {
if (fxp_add_rfabuf(sc, NULL) != 0) {
goto malloc_fail;
@ -270,6 +286,9 @@ fxp_attach(config_id, unit)
printf("fxp%d: Ethernet address %s\n", unit,
ether_sprintf(sc->arpcom.ac_enaddr));
/*
* Attach the interface.
*/
if_attach(ifp);
#if NBPFILTER > 0
bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
@ -409,6 +428,9 @@ fxp_start(ifp)
ifp->if_flags |= IFF_OACTIVE;
return;
}
/*
* Grab a packet to transmit.
*/
IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, mb_head);
if (mb_head == NULL) {
/*
@ -417,6 +439,9 @@ fxp_start(ifp)
return;
}
/*
* Get pointer to next available (unused) descriptor.
*/
txp = sc->cbl_last->next;
/*
@ -550,12 +575,19 @@ fxp_intr(arg)
struct fxp_rfa *rfa;
rcvloop:
m = sc->rfa_headm;
rfa = (struct fxp_rfa *)(mtod(m, u_long) & ~(MCLBYTES - 1));
rfa = (struct fxp_rfa *)m->m_ext.ext_buf;
if (rfa->rfa_status & FXP_RFA_STATUS_C) {
/*
* Remove first packet from the chain.
*/
sc->rfa_headm = m->m_next;
m->m_next = NULL;
/*
* Add a new buffer to the receive chain. If this
* fails, the old buffer is recycled instead.
*/
if (fxp_add_rfabuf(sc, m) == 0) {
struct ether_header *eh;
u_short total_len;
@ -589,8 +621,7 @@ fxp_intr(arg)
ifp->if_ierrors++;
fxp_scb_wait(csr);
csr->scb_general = vtophys(mtod(sc->rfa_headm, u_long) &
~(MCLBYTES - 1));
csr->scb_general = vtophys(sc->rfa_headm->m_ext.ext_buf);
csr->scb_command = FXP_SCB_COMMAND_RU_START;
}
}
@ -599,6 +630,17 @@ fxp_intr(arg)
return found;
}
/*
* Update packet in/out/collision statistics. The i82557 doesn't
* allow you to access these counters without doing a fairly
* expensive DMA to get _all_ of the statistics it maintains, so
* we do this operation here only once per second. The statistics
* counters in the kernel are updated from the previous dump-stats
* DMA and then a new dump-stats DMA is started. The on-chip
* counters are zeroed when the DMA completes. If we can't start
* the DMA immediately, we don't wait - we just prepare to read
* them again next time.
*/
void
fxp_stats_update(arg)
void *arg;
@ -616,19 +658,24 @@ fxp_stats_update(arg)
* around. Make sure we don't count the stats twice
* however.
*/
if (sc->csr->scb_command & FXP_SCB_COMMAND_MASK) {
if ((sc->csr->scb_command & FXP_SCB_COMMAND_MASK) == 0) {
/*
* Start another stats dump. By waiting for it to be
* accepted, we avoid having to do splhigh locking when
* writing scb_command in other parts of the driver.
*/
sc->csr->scb_command = FXP_SCB_COMMAND_CU_DUMPRESET;
fxp_scb_wait(sc);
} else {
/*
* A previous command is still waiting to be accepted.
* Just zero our copy of the stats and wait for the
* next timer event to pdate them.
*/
sp->tx_good = 0;
sp->tx_total_collisions = 0;
sp->rx_good = 0;
return;
}
/*
* Start another stats dump. By waiting for it to be accepted,
* we avoid having to do splhigh locking when writing scb_command
* in other parts of the driver.
*/
sc->csr->scb_command = FXP_SCB_COMMAND_CU_DUMPRESET;
fxp_scb_wait(sc);
/*
* Schedule another timeout one second from now.
*/
@ -830,7 +877,7 @@ fxp_init(unit)
* Initialize receiver buffer area - RFA.
*/
fxp_scb_wait(csr);
csr->scb_general = vtophys(mtod(sc->rfa_headm, u_long) & ~(MCLBYTES - 1));
csr->scb_general = vtophys(sc->rfa_headm->m_ext.ext_buf);
csr->scb_command = FXP_SCB_COMMAND_RU_START;
ifp->if_flags |= IFF_RUNNING;
@ -879,8 +926,12 @@ fxp_add_rfabuf(sc, oldm)
rfa->actual_size = 0;
rfa->size = MCLBYTES - sizeof(struct fxp_rfa);
m->m_data += sizeof(struct fxp_rfa);
/*
* If there are other buffers already on the list, attach this
* one to the end by fixing up the tail to point to this one.
*/
if (sc->rfa_headm != NULL) {
p_rfa = (struct fxp_rfa *) (mtod(sc->rfa_tailm, u_long) & ~(MCLBYTES - 1));
p_rfa = (struct fxp_rfa *) sc->rfa_tailm->m_ext.ext_buf;
sc->rfa_tailm->m_next = m;
p_rfa->link_addr = vtophys(rfa);
p_rfa->rfa_control &= ~FXP_RFA_CONTROL_EL;
@ -889,7 +940,7 @@ fxp_add_rfabuf(sc, oldm)
}
sc->rfa_tailm = m;
return m == oldm ? 1 : 0;
return (m == oldm);
}
static int