/*
 * DF-3778 trigger analysis - jme_rxeof() unbounded walk in interrupt context.
 * Annotated excerpt of sys/dev/netif/jme/if_jme.c (verbatim, 2026-09-16 tree).
 *
 * jme_rxeof() walks completed RX descriptors in an unbounded for(;;):
 *
 *   sys/dev/netif/jme/if_jme.c:2488-2562
 *
 *   static void
 *   jme_rxeof(struct jme_rxdata *rdata, int count, int cpuid)
 *   {
 *           struct jme_desc *desc;
 *           int nsegs, pktlen;
 *
 *           for (;;) {
 *   #ifdef IFPOLL_ENABLE
 *                   if (count >= 0 && count-- == 0)     // <-- the ONLY bound
 *                           break;                      //     (:2496-2497)
 *   #endif
 *                   desc = &rdata->jme_rx_ring[rdata->jme_rx_cons];
 *                   if ((le32toh(desc->flags) & JME_RD_OWN) == JME_RD_OWN)
 *                           break;                      // ring drained
 *                   ...
 *                   jme_rxpkt(rdata, cpuid);            // m_getcl + dmamap
 *                                                           load + if_input
 *                                                           per frame
 *           }
 *   }
 *
 * The bound exists ONLY when count >= 0.  Call sites:
 *
 *   :418   jme_miibus_statchg      jme_rxeof(rdata, -1, -1)   // drain @reconfig
 *   :3341  jme_npoll_rx            jme_rxeof(rdata, cycle, mycpuid)  // BOUNDED
 *   :3500  jme_rx_intr             jme_rxeof(rdata, -1, cpuid)   // legacy/MSI
 *   :3845  jme_msix_rx             jme_rxeof(rdata, -1, mycpuid) // MSI-X RX
 *   :3882  jme_rx_restart          jme_rxeof(rdata, -1, cpuid)   // MSI-X/poll sts
 *
 * The interrupt-context call sites (3500/3845/3882) all pass -1, i.e. the
 * walk exits only when the ring drains (OWN set) - and each iteration is
 * us-scale (jme_newbuf: m_getcl + bus_dmamap_load_mbuf_segment, if_jme.c:3061-
 * 3074; if_input dispatch), which is SLOWER than 64-byte line-rate arrival
 * on 1GbE (1.488 Mpps = 672ns/packet budget).  Under a sustained small-
 * packet flood the ring is perpetually non-empty:
 *
 *   - jme_msix_rx holds rdata->jme_rx_serialize for the whole walk
 *     (ASSERT_SERIALIZED :3837; registered with that serializer at :3672),
 *     so that ring's netisr/IRQ CPU spins at 100% and every other entry
 *     point on the ring blocks;
 *   - jme_rx_intr (from jme_intr :2150, registered on sc->jme_serialize
 *     :3912) enters each ring serializer in turn (:3499) after taking the
 *     MAIN serializer -> the whole interface wedges behind the walk;
 *   - jme_msix_status / jme_npoll_status -> jme_rx_restart likewise.
 *
 * The driver itself proves the loop is boundable: the ifpoll path passes
 * `cycle` (:3341).  DragonFly's sibling alc(4) driver had the same defect
 * filed as DF-3761 (process_limit knob existed but was never read);
 * msk(4) bounds its own walk (sys/dev/netif/msk/if_msk.c rxprog vs
 * msk_process_limit).  jme has NO bound knob at all for the interrupt
 * path (grep process_limit -> 0 hits, see run.log).
 *
 * Mitigating difference vs alc(4): jme is 1GbE-only (JMC250; JMC260 is
 * 100MbE), so the flood rate ceiling is 1.488 Mpps; the livelock
 * reasoning still holds because per-frame kernel work exceeds the 672ns
 * inter-arrival budget (m_getcl + dmamap load + if_input alone).
 *
 * Trigger: remote, unauthenticated, default configuration - flood the
 * interface with minimum-size frames at line rate while it is up.
 *
 * Fix (fix.diff): bound the three interrupt-context call sites with a
 * jme_rx_proc_limit knob (default 64, tunable hw.jme.rx_proc_limit),
 * exactly the bound the ifpoll path already applies.  Safe because every
 * one of those handlers masks its interrupt on entry and re-enables it
 * at exit (jme_msix_rx :3839/:3847, jme_intr :2125/:2174, jme_msix_status
 * :3859/:3869): a bounded early exit with work remaining re-interrupts
 * immediately.  The :418 statchg drain is intentionally left unbounded
 * (link reconfiguration quiesce path, interrupts masked, must fully
 * drain before the ring pointers are reset).
 */
