OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
fxp interrupts coalescing

From: Michael Shalayeff (mickeylucifier.net)
Date: Mon Aug 02 2004 - 20:18:21 CDT


re
here is a diff that implemets interrupts coalescing
on 82558 and later chips. it loads a microcode
that sets the parameters (a msg printed into dmesg).
the default max delay for an interrupt after first
packet received is 64ms and max number of packets
to accumulate before generating an interrupt is 16.
any packets smaller than 128 bytes will be reported
immidiately w/o any delays (for tcp acks and stuff).

please test before and after and see if any particular
troubles arise (such as slower tcp).
the number of interrupts (on ping -f -s128) shall
decrease and interrupt time (in top) go down as well.
revision 1 chips do not support it.

the code came from freebsd w/ hacking by dmitry bogdan and meself...

10x
cu
--
    paranoic mickey (my employers have changed but, the name has remained)

Index: cardbus/if_fxp_cardbus.c
===================================================================
RCS file: /cvs/src/sys/dev/cardbus/if_fxp_cardbus.c,v
retrieving revision 1.7
diff -u -u -b -w -r1.7 if_fxp_cardbus.c
--- cardbus/if_fxp_cardbus.c 27 Jun 2004 02:38:37 -0000 1.7
+++ cardbus/if_fxp_cardbus.c 31 Jul 2004 19:16:12 -0000
-196,6 +196,8
                 return;
         }
         snprintf(intrstr, sizeof(intrstr), "irq %d", ca->ca_intrline);
+
+ sc->sc_revision = PCI_REVISION(ca->ca_class);
 
         fxp_attach_common(sc, intrstr);
 }
Index: ic/fxp.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/fxp.c,v
retrieving revision 1.55
diff -u -u -b -w -r1.55 fxp.c
--- ic/fxp.c 12 Jul 2004 20:57:32 -0000 1.55
+++ ic/fxp.c 31 Jul 2004 21:08:26 -0000
-159,6 +159,7
 void fxp_start(struct ifnet *);
 int fxp_ioctl(struct ifnet *, u_long, caddr_t);
 void fxp_init(void *);
+void fxp_load_ucode(struct fxp_softc *);
 void fxp_stop(struct fxp_softc *, int);
 void fxp_watchdog(struct ifnet *);
 int fxp_add_rfabuf(struct fxp_softc *, struct mbuf *);
-180,6 +181,12
 static int tx_threshold = 64;
 
 /*
+ * Interrupts coalescing code params
+ */
+int fxp_int_delay = FXP_INT_DELAY;
+int fxp_bundle_max = FXP_BUNDLE_MAX;
+
+/*
  * TxCB list index mask. This is used to do list wrap-around.
  */
 #define FXP_TXCB_MASK (FXP_NTXCB - 1)
-432,6 +439,13
         sc->phy_10Mbps_only = data >> 15;
 
         /*
+ * Only 82558 and newer cards can do this.
+ */
+ if (sc->sc_revision >= FXP_REV_82558_A4) {
+ sc->sc_int_delay = fxp_int_delay;
+ sc->sc_bundle_max = fxp_bundle_max;
+ }
+ /*
          * Read MAC address.
          */
         fxp_read_eeprom(sc, (u_int16_t *)enaddr, 0, 3);
-1230,6 +1244,9
         CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0);
         fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_BASE);
 
+#ifndef SMALL_KERNEL
+ fxp_load_ucode(sc);
+#endif
         /* Once through to set flags */
         fxp_mc_setup(sc, 0);
 
-1825,3 +1842,106
                 FXP_MCS_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
         } while (!(mcsp->cb_status & htole16(FXP_CB_STATUS_C)));
 }
+
+#ifndef SMALL_KERNEL
+#include <dev/microcode/fxp/rcvbundl.h>
+
+const u_int32_t fxp_ucode_d101a[] = D101_A_RCVBUNDLE_UCODE;
+const u_int32_t fxp_ucode_d101b0[] = D101_B0_RCVBUNDLE_UCODE;
+const u_int32_t fxp_ucode_d101ma[] = D101M_B_RCVBUNDLE_UCODE;
+const u_int32_t fxp_ucode_d101s[] = D101S_RCVBUNDLE_UCODE;
+const u_int32_t fxp_ucode_d102[] = D102_B_RCVBUNDLE_UCODE;
+const u_int32_t fxp_ucode_d102c[] = D102_C_RCVBUNDLE_UCODE;
+
+#define UCODE(x) x, sizeof(x)
+
+struct ucode {
+ u_int32_t revision;
+ const u_int32_t *ucode;
+ int length;
+ u_int16_t int_delay_offset;
+ u_int16_t bundle_max_offset;
+} const ucode_table[] = {
+ { FXP_REV_82558_A4, UCODE(fxp_ucode_d101a),
+ D101_CPUSAVER_DWORD, 0 },
+
+ { FXP_REV_82558_B0, UCODE(fxp_ucode_d101b0),
+ D101_CPUSAVER_DWORD, 0 },
+
+ { FXP_REV_82559_A0, UCODE(fxp_ucode_d101ma),
+ D101M_CPUSAVER_DWORD, D101M_CPUSAVER_BUNDLE_MAX_DWORD },
+
+ { FXP_REV_82559S_A, UCODE(fxp_ucode_d101s),
+ D101S_CPUSAVER_DWORD, D101S_CPUSAVER_BUNDLE_MAX_DWORD },
+
+ { FXP_REV_82550, UCODE(fxp_ucode_d102),
+ D102_B_CPUSAVER_DWORD, D102_B_CPUSAVER_BUNDLE_MAX_DWORD },
+
+ { FXP_REV_82550_C, UCODE(fxp_ucode_d102c),
+ D102_C_CPUSAVER_DWORD, D102_C_CPUSAVER_BUNDLE_MAX_DWORD },
+
+ { 0, NULL, 0, 0, 0 }
+};
+
+void
+fxp_load_ucode(struct fxp_softc *sc)
+{
+ const struct ucode *uc;
+ struct fxp_cb_ucode *cbp = &sc->sc_ctrl->u.code;
+ int i;
+
+ if (sc->sc_flags & FXPF_UCODE)
+ return;
+
+ for (uc = ucode_table; uc->ucode != NULL; uc++)
+ if (sc->sc_revision == uc->revision)
+ break;
+ if (uc->ucode == NULL)
+ return; /* no ucode for this chip found */
+
+ cbp->cb_status = 0;
+ cbp->cb_command = htole16(FXP_CB_COMMAND_UCODE|FXP_CB_COMMAND_EL);
+ cbp->link_addr = 0xffffffff; /* (no) next command */
+ for (i = 0; i < uc->length; i++)
+ cbp->ucode[i] = htole32(uc->ucode[i]);
+
+ if (uc->int_delay_offset)
+ *((u_int16_t *)&cbp->ucode[uc->int_delay_offset]) =
+ htole16(sc->sc_int_delay + sc->sc_int_delay / 2);
+
+ if (uc->bundle_max_offset)
+ *((u_int16_t *)&cbp->ucode[uc->bundle_max_offset]) =
+ htole16(sc->sc_bundle_max);
+
+ FXP_UCODE_SYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+ /*
+ * Download the ucode to the chip.
+ */
+ fxp_scb_wait(sc);
+ CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->tx_cb_map->dm_segs->ds_addr
+ + offsetof(struct fxp_ctrl, u.code));
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
+
+ /* ...and wait for it to complete. */
+ i = 10000;
+ do {
+ DELAY(2);
+ FXP_UCODE_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ } while (((cbp->cb_status & htole16(FXP_CB_STATUS_C)) == 0) && --i);
+ if (i == 0) {
+ printf("%s: timeout loading microcode\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ printf("%s: microcode loaded, int_delay: %d usec",
+ sc->sc_dev.dv_xname, sc->sc_int_delay);
+
+ if (uc->bundle_max_offset)
+ printf("bundle_max %d\n", sc->sc_bundle_max);
+ else
+ printf("\n");
+
+ sc->sc_flags |= FXPF_UCODE;
+}
+#endif /* SMALL_KERNEL */
Index: ic/fxpreg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/fxpreg.h,v
retrieving revision 1.5
diff -u -u -b -w -r1.5 fxpreg.h
--- ic/fxpreg.h 21 Oct 2003 18:58:49 -0000 1.5
+++ ic/fxpreg.h 31 Jul 2004 19:12:30 -0000
-198,7 +198,7
 #define FXP_CB_COMMAND_CONFIG 0x2
 #define FXP_CB_COMMAND_MCAS 0x3
 #define FXP_CB_COMMAND_XMIT 0x4
-#define FXP_CB_COMMAND_RESRV 0x5
+#define FXP_CB_COMMAND_UCODE 0x5
 #define FXP_CB_COMMAND_DUMP 0x6
 #define FXP_CB_COMMAND_DIAG 0x7
 /* command flags */
-315,3 +315,22
 #define FXP_DP83840_PCR_F_CONNECT 0x0020 /* 1 = force link disconnect function bypass */
 #define FXP_DP83840_PCR_BIT8 0x0100
 #define FXP_DP83840_PCR_BIT10 0x0400
+
+#define MAXUCODESIZE 192
+struct fxp_cb_ucode {
+ volatile u_int16_t cb_status;
+ volatile u_int16_t cb_command;
+ volatile u_int32_t link_addr;
+ volatile u_int32_t ucode[MAXUCODESIZE];
+};
+
+/*
+ * Chip revision values.
+ */
+#define FXP_REV_82557 1
+#define FXP_REV_82558_A4 4
+#define FXP_REV_82558_B0 5
+#define FXP_REV_82559_A0 8
+#define FXP_REV_82559S_A 9
+#define FXP_REV_82550 12
+#define FXP_REV_82550_C 13
Index: ic/fxpvar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/fxpvar.h,v
retrieving revision 1.17
diff -u -u -b -w -r1.17 fxpvar.h
--- ic/fxpvar.h 27 Jun 2004 02:38:38 -0000 1.17
+++ ic/fxpvar.h 31 Jul 2004 21:32:38 -0000
-52,9 +52,28
 #define FXP_NRFABUFS_MAX 64 /* These are large so choose wisely. */
 
 /*
+ * Default maximum time, in microseconds, that an interrupt may be delayed
+ * in an attempt to coalesce interrupts. This is only effective if the Intel
+ * microcode is loaded.
+ */
+#ifndef FXP_INT_DELAY
+#define FXP_INT_DELAY 64
+#endif
+
+/*
+ * Default number of packets that will be bundled, before an interrupt is
+ * generated. This is only effective if the Intel microcode is loaded.
+ * This is not present in all microcode revisions.
+ */
+#ifndef FXP_BUNDLE_MAX
+#define FXP_BUNDLE_MAX 16
+#endif
+
+/*
  * NOTE: Elements are ordered for optimal cacheline behavior, and NOT
  * for functional grouping.
  */
+
 struct fxp_txsw {
         struct fxp_txsw *tx_next;
         struct mbuf *tx_mbuf;
-70,6 +89,7
                 struct fxp_cb_mcs mcs;
                 struct fxp_cb_ias ias;
                 struct fxp_cb_config cfg;
+ struct fxp_cb_ucode code;
         } u;
 };
 
-88,6 +108,7
 #define FXPF_FIX_RESUME_BUG 0x10 /* currently need to work-around
                                            the resume bug */
 #define FXPF_DISABLE_STANDBY 0x20 /* currently need to work-around */
+#define FXPF_UCODE 0x40 /* ucode is loaded */
         struct timeout stats_update_to; /* Pointer to timeout structure */
         int rx_idle_secs; /* # of seconds RX has been idle */
         struct fxp_cb_tx *cbl_base; /* base of TxCB list */
-108,6 +129,9
         struct fxp_ctrl *sc_ctrl;
         bus_dmamap_t sc_rxmaps[FXP_NRFABUFS_MAX];
         int sc_rxfree;
+ u_int32_t sc_revision; /* chip revision */
+ u_int16_t sc_int_delay; /* interrupt delay value for ucode */
+ u_int16_t sc_bundle_max; /* max # frames per interrupt (ucode) */
 };
 
 /* Macros to ease CSR access. */
-146,6 +170,10
 #define FXP_CFG_SYNC(sc, p) \
     bus_dmamap_sync((sc)->sc_dmat, (sc)->tx_cb_map, \
         offsetof(struct fxp_ctrl, u.cfg), sizeof(struct fxp_cb_config), (p))
+
+#define FXP_UCODE_SYNC(sc, p) \
+ bus_dmamap_sync((sc)->sc_dmat, (sc)->tx_cb_map, \
+ offsetof(struct fxp_ctrl, u.code), sizeof(struct fxp_cb_ucode), (p))
 
 #define FXP_STATS_SYNC(sc, p) \
     bus_dmamap_sync((sc)->sc_dmat, (sc)->tx_cb_map, \
Index: pci/if_fxp_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_fxp_pci.c,v
retrieving revision 1.27
diff -u -u -b -w -r1.27 if_fxp_pci.c
--- pci/if_fxp_pci.c 27 Jun 2004 02:38:38 -0000 1.27
+++ pci/if_fxp_pci.c 31 Jul 2004 19:16:01 -0000
-143,6 +143,8
                 return;
         }
         sc->sc_dmat = pa->pa_dmat;
+
+ sc->sc_revision = rev;
 
         /*
          * Allocate our interrupt.