emx(4): Pass packet info to ether_input_chain()
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 22 Mar 2009 07:45:14 +0000 (15:45 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 22 Mar 2009 07:45:14 +0000 (15:45 +0800)
sys/dev/netif/emx/if_emx.c
sys/dev/netif/emx/if_emx.h

index 9fe7841..5b7c9f6 100644 (file)
@@ -93,6 +93,7 @@
 #include <net/if_media.h>
 #include <net/ifq_var.h>
 #include <net/toeplitz.h>
+#include <net/toeplitz2.h>
 #include <net/vlan/if_vlan_var.h>
 #include <net/vlan/if_vlan_ether.h>
 
@@ -320,6 +321,45 @@ emx_rxcsum(uint32_t staterr, struct mbuf *mp)
        }
 }
 
+static __inline struct pktinfo *
+emx_rssinfo(struct mbuf *m, struct pktinfo *pi,
+           uint32_t mrq, uint32_t hash, uint32_t staterr)
+{
+       switch (mrq & EMX_RXDMRQ_RSSTYPE_MASK) {
+       case EMX_RXDMRQ_IPV4_TCP:
+               pi->pi_netisr = NETISR_IP;
+               pi->pi_flags = 0;
+               pi->pi_l3proto = IPPROTO_TCP;
+               break;
+
+       case EMX_RXDMRQ_IPV6_TCP:
+               pi->pi_netisr = NETISR_IPV6;
+               pi->pi_flags = 0;
+               pi->pi_l3proto = IPPROTO_TCP;
+               break;
+
+       case EMX_RXDMRQ_IPV4:
+               if (staterr & E1000_RXD_STAT_IXSM)
+                       return NULL;
+
+               if ((staterr &
+                    (E1000_RXD_STAT_TCPCS | E1000_RXDEXT_STATERR_TCPE)) ==
+                   E1000_RXD_STAT_TCPCS) {
+                       pi->pi_netisr = NETISR_IP;
+                       pi->pi_flags = 0;
+                       pi->pi_l3proto = IPPROTO_UDP;
+                       break;
+               }
+               /* FALL THROUGH */
+       default:
+               return NULL;
+       }
+
+       m->m_flags |= M_HASH;
+       m->m_pkthdr.hash = toeplitz_hash(hash);
+       return pi;
+}
+
 static int
 emx_probe(device_t dev)
 {
@@ -2779,6 +2819,7 @@ emx_rxeof(struct emx_softc *sc, int ring_idx, int count)
        ether_input_chain_init(chain);
 
        while ((staterr & E1000_RXD_STAT_DD) && count != 0) {
+               struct pktinfo *pi = NULL, pi0;
                struct emx_rxbuf *rx_buf = &rdata->rx_buf[i];
                struct mbuf *m = NULL;
                int eop, len;
@@ -2857,6 +2898,10 @@ emx_rxeof(struct emx_softc *sc, int ring_idx, int count)
                                rdata->fmp = NULL;
                                rdata->lmp = NULL;
 
+                               if (ifp->if_capenable & IFCAP_RSS) {
+                                       pi = emx_rssinfo(m, &pi0, mrq,
+                                                        rss_hash, staterr);
+                               }
 #ifdef EMX_RSS_DEBUG
                                rdata->rx_pkts++;
 #endif
@@ -2874,7 +2919,7 @@ discard:
                }
 
                if (m != NULL)
-                       ether_input_chain(ifp, m, NULL, chain);
+                       ether_input_chain(ifp, m, pi, chain);
 
                /* Advance our pointers to the next descriptor. */
                if (++i == rdata->num_rx_desc)
index d7471f3..1c1e466 100644 (file)
@@ -190,6 +190,13 @@ typedef union e1000_rx_desc_extended       emx_rxdesc_t;
 #define rxd_mrq                wb.lower.mrq            /* 32bits */
 #define rxd_rss                wb.lower.hi_dword.rss   /* 32bits */
 
+#define EMX_RXDMRQ_RSSTYPE_MASK        0xf
+#define EMX_RXDMRQ_NO_HASH     0
+#define EMX_RXDMRQ_IPV4_TCP    1
+#define EMX_RXDMRQ_IPV4                2
+#define EMX_RXDMRQ_IPV6_TCP    3
+#define EMX_RXDMRQ_IPV6                5
+
 struct emx_rxdata {
        /*
         * Receive definitions