Author: bz
Date: Fri May  9 12:59:38 2014
New Revision: 265766
URL: http://svnweb.freebsd.org/changeset/base/265766

Log:
  Adjust the register layout to allow for 64bit registers in the
  future for nf10bmac(4).  Also, add support for and enable RX interrupts.
  
  MFC after:    2 weeks

Modified:
  head/sys/boot/fdt/dts/mips/beri-netfpga.dts
  head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c
  head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c
  head/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h

Modified: head/sys/boot/fdt/dts/mips/beri-netfpga.dts
==============================================================================
--- head/sys/boot/fdt/dts/mips/beri-netfpga.dts Fri May  9 12:13:22 2014        
(r265765)
+++ head/sys/boot/fdt/dts/mips/beri-netfpga.dts Fri May  9 12:59:38 2014        
(r265766)
@@ -135,13 +135,14 @@
 
                ethernet@7f005000 {
                        compatible = "netfpag10g,nf10bmac";
-                       // TX, RX, LOOP
-                       reg = <0x7f005010 0xc
-                              0x7f005020 0xc
-                              0x7f005030 0x4>;
+                       // LOOP, TX, RX, INTR
+                       reg = <0x7f005000 0x20
+                              0x7f005020 0x30
+                              0x7f005050 0x30
+                              0x7f005100 0x10>;
                        // RX
-                       #interrupts = <1>;
-                       #interrupt-parent = <&beripic>;
+                       interrupts = <1>;
+                       interrupt-parent = <&beripic>;
                };
        };
 

Modified: head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c
==============================================================================
--- head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c      Fri May  9 12:13:22 
2014        (r265765)
+++ head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c      Fri May  9 12:59:38 
2014        (r265766)
@@ -92,13 +92,15 @@ static poll_handler_t nf10bmac_poll;
 #define        NF10BMAC_LOCK_ASSERT(_sc)       \
        mtx_assert(&(_sc)->nf10bmac_mtx, MA_OWNED)
 
-#define        NF10BMAC_TX_LEN                 0x08
-#define        NF10BMAC_TX_META                0x04
+#define        NF10BMAC_CTRL0                  0x00
 #define        NF10BMAC_TX_DATA                0x00
-#define        NF10BMAC_RX_LEN                 0x08
-#define        NF10BMAC_RX_META                0x04
+#define        NF10BMAC_TX_META                0x08
+#define        NF10BMAC_TX_LEN                 0x10
 #define        NF10BMAC_RX_DATA                0x00
-#define        NF10BMAC_CTRL0                  0x00
+#define        NF10BMAC_RX_META                0x08
+#define        NF10BMAC_RX_LEN                 0x10
+#define        NF10BMAC_INTR_CLEAR_DIS         0x00
+#define        NF10BMAC_INTR_CTRL              0x08
 
 #define NF10BMAC_TUSER_MAC0            (1 << 0)
 #define NF10BMAC_TUSER_CPU0            (1 << 1)
@@ -109,11 +111,12 @@ static poll_handler_t nf10bmac_poll;
 #define NF10BMAC_TUSER_MAC3            (1 << 6)
 #define NF10BMAC_TUSER_CPU3            (1 << 7)
 
+#define        NF10BMAC_DATA_LEN_MASK          0x0000ffff
 #define        NF10BMAC_DATA_DPORT_MASK        0xff000000
 #define        NF10BMAC_DATA_DPORT_SHIFT       24
 #define        NF10BMAC_DATA_SPORT_MASK        0x00ff0000
 #define        NF10BMAC_DATA_SPORT_SHIFT       16
-#define        NF10BMAC_DATA_LAST              0x00000080
+#define        NF10BMAC_DATA_LAST              0x00008000
 #define        NF10BMAC_DATA_STRB              0x0000000f
 
 
@@ -151,7 +154,7 @@ nf10bmac_read_4_be(struct resource *res,
 }
 
 #define        NF10BMAC_WRITE_CTRL_4(sc, reg, val)                             
\
-       nf10bmac_write_4((sc)->nf10bmac_mem_res, (reg), (val),          \
+       nf10bmac_write_4((sc)->nf10bmac_ctrl_res, (reg), (val),         \
            __func__, __LINE__)
 #define        NF10BMAC_WRITE_4(sc, reg, val)                                  
\
        nf10bmac_write_4((sc)->nf10bmac_tx_mem_res, (reg), (val),       \
@@ -166,6 +169,21 @@ nf10bmac_read_4_be(struct resource *res,
        nf10bmac_read_4_be((sc)->nf10bmac_rx_mem_res, (reg),            \
            __func__, __LINE__)
 
+#define        NF10BMAC_WRITE_INTR_4(sc, reg, val, _f, _l)                     
\
+       nf10bmac_write_4((sc)->nf10bmac_intr_res, (reg), (val),         \
+           (_f), (_l))
+
+#define        NF10BMAC_RX_INTR_CLEAR_DIS(sc)                                  
\
+       NF10BMAC_WRITE_INTR_4((sc), NF10BMAC_INTR_CLEAR_DIS, 1,         \
+       __func__, __LINE__)
+#define        NF10BMAC_RX_INTR_ENABLE(sc)                                     
\
+       NF10BMAC_WRITE_INTR_4((sc), NF10BMAC_INTR_CTRL, 1,              \
+       __func__, __LINE__)
+#define        NF10BMAC_RX_INTR_DISABLE(sc)                                    
\
+       NF10BMAC_WRITE_INTR_4((sc), NF10BMAC_INTR_CTRL, 0,              \
+       __func__, __LINE__)
+
+
 #ifdef ENABLE_WATCHDOG
 static void nf10bmac_tick(void *);
 #endif
@@ -318,7 +336,7 @@ nf10bmac_rx_locked(struct nf10bmac_softc
         * skip to tlast).
         */
 
-       len = NF10BMAC_READ_4(sc, NF10BMAC_RX_LEN);
+       len = NF10BMAC_READ_4(sc, NF10BMAC_RX_LEN) & NF10BMAC_DATA_LEN_MASK;
        if (len > (MCLBYTES - ETHER_ALIGN)) {
                nf10bmac_eat_packet_munch_munch(sc);
                return (0);
@@ -435,6 +453,7 @@ nf10bmac_stop_locked(struct nf10bmac_sof
 
        ifp = sc->nf10bmac_ifp;
        ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+       NF10BMAC_RX_INTR_CLEAR_DIS(sc);
 
        sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK;
        if_link_state_change(ifp, LINK_STATE_DOWN);
@@ -498,6 +517,16 @@ nf10bmac_init_locked(struct nf10bmac_sof
        /* Instead drain the FIFO; or at least a possible first packet.. */
        nf10bmac_eat_packet_munch_munch(sc);
 
+#ifdef DEVICE_POLLING
+       /* Only enable interrupts if we are not polling. */
+       if (ifp->if_capenable & IFCAP_POLLING) {
+               NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+       } else
+#endif
+       {
+               NF10BMAC_RX_INTR_ENABLE(sc);
+       }
+
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
        ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
@@ -556,6 +585,49 @@ nf10bmac_tick(void *xsc)
 }
 #endif
 
+static void
+nf10bmac_intr(void *arg)
+{
+       struct nf10bmac_softc *sc;
+       struct ifnet *ifp;
+       int rx_npkts;
+
+       sc = (struct nf10bmac_softc *)arg;
+       ifp = sc->nf10bmac_ifp;
+
+       NF10BMAC_LOCK(sc);
+#ifdef DEVICE_POLLING
+       if (ifp->if_capenable & IFCAP_POLLING) {
+               NF10BMAC_UNLOCK(sc);
+               return;
+       } 
+#endif
+
+       /* NF10BMAC_RX_INTR_DISABLE(sc); */
+       NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+
+       /* We only have an RX interrupt and no status information. */
+       rx_npkts = 0;
+       while (rx_npkts < NF10BMAC_MAX_PKTS) {
+               int c;
+
+               c = nf10bmac_rx_locked(sc);
+               rx_npkts += c;
+               if (c == 0)
+                       break;
+       }
+
+       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+               /* Re-enable interrupts. */
+               NF10BMAC_RX_INTR_ENABLE(sc);
+
+               if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+                       nf10bmac_start_locked(ifp);
+       }
+       NF10BMAC_UNLOCK(sc);
+}
+
+
 #ifdef DEVICE_POLLING
 static int
 nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
@@ -649,10 +721,16 @@ nf10bmac_ioctl(struct ifnet *ifp, u_long
                                        break;
                                }
 
+                               NF10BMAC_RX_INTR_CLEAR_DIS(sc);
+
                        /*
                         * Do not allow disabling of polling if we do
                         * not have interrupts.
                         */
+                       } else if (sc->nf10bmac_rx_irq_res != NULL) {
+                               error = ether_poll_deregister(ifp);
+                               /* Enable interrupts. */
+                               NF10BMAC_RX_INTR_ENABLE(sc);
                        } else {
                                ifp->if_capenable ^= IFCAP_POLLING;
                                error = EINVAL;
@@ -673,7 +751,6 @@ nf10bmac_ioctl(struct ifnet *ifp, u_long
        return (error);
 }
 
-
 /*
  * Generic device handling routines.
  */
@@ -733,18 +810,40 @@ nf10bmac_attach(device_t dev)
         ifmedia_add(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T, 0, NULL);
         ifmedia_set(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T);
 
-       /* Interrupts would go here. */
+       /* Initialise. */
+       error = 0;
+
+       /* Hook up interrupts. Well the one. */
+       if (sc->nf10bmac_rx_irq_res != NULL) {
+               error = bus_setup_intr(dev, sc->nf10bmac_rx_irq_res,
+                   INTR_TYPE_NET | INTR_MPSAFE, NULL, nf10bmac_intr,
+                   sc, &sc->nf10bmac_rx_intrhand);
+               if (error != 0) {
+                       device_printf(dev, "enabling RX IRQ failed\n");
+                       ether_ifdetach(ifp);
+                       goto err;
+               }
+       }
 
+       if ((ifp->if_capenable & IFCAP_POLLING) != 0 ||
+           sc->nf10bmac_rx_irq_res == NULL) {
 #ifdef DEVICE_POLLING
-       ifp->if_capenable |= IFCAP_POLLING;
-       device_printf(dev, "forcing to polling due to no interrupts\n");
-       error = ether_poll_register(nf10bmac_poll, ifp);
-       if (error != 0)
-               goto err;
+               /* If not on and no IRQs force it on. */
+               if (sc->nf10bmac_rx_irq_res == NULL) {
+                       ifp->if_capenable |= IFCAP_POLLING;
+                       device_printf(dev,
+                           "forcing to polling due to no interrupts\n");
+               }
+               error = ether_poll_register(nf10bmac_poll, ifp);
+               if (error != 0)
+                       goto err;
 #else
-       device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
-       error = ENXIO;
+               device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
+               error = ENXIO;
 #endif
+       } else {
+               NF10BMAC_RX_INTR_ENABLE(sc);
+       }
 
 err:
        if (error != 0)
@@ -780,6 +879,10 @@ nf10bmac_detach(device_t dev)
                ether_ifdetach(ifp);
        }
 
+       if (sc->nf10bmac_rx_intrhand)
+               bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res,
+                   sc->nf10bmac_rx_intrhand);
+
        if (ifp != NULL)
                if_free(ifp);
        ifmedia_removeall(&sc->nf10bmac_media);
@@ -797,10 +900,15 @@ nf10bmac_detach_resources(device_t dev)
 
        sc = device_get_softc(dev);
 
-       if (sc->nf10bmac_mem_res != NULL) {
+       if (sc->nf10bmac_rx_irq_res != NULL) {
+               bus_release_resource(dev, SYS_RES_IRQ, sc->nf10bmac_rx_irq_rid,
+                   sc->nf10bmac_rx_irq_res);
+               sc->nf10bmac_rx_irq_res = NULL;
+       }
+       if (sc->nf10bmac_intr_res != NULL) {
                bus_release_resource(dev, SYS_RES_MEMORY,
-                   sc->nf10bmac_mem_rid, sc->nf10bmac_mem_res);
-               sc->nf10bmac_mem_res = NULL;
+                   sc->nf10bmac_intr_rid, sc->nf10bmac_intr_res);
+               sc->nf10bmac_intr_res = NULL;
        }
        if (sc->nf10bmac_rx_mem_res != NULL) {
                bus_release_resource(dev, SYS_RES_MEMORY,
@@ -812,6 +920,11 @@ nf10bmac_detach_resources(device_t dev)
                    sc->nf10bmac_tx_mem_rid, sc->nf10bmac_tx_mem_res);
                sc->nf10bmac_tx_mem_res = NULL;
        }
+       if (sc->nf10bmac_ctrl_res != NULL) {
+               bus_release_resource(dev, SYS_RES_MEMORY,
+                   sc->nf10bmac_ctrl_rid, sc->nf10bmac_ctrl_res);
+               sc->nf10bmac_ctrl_res = NULL;
+       }
 }
 
 int

Modified: head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c
==============================================================================
--- head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c  Fri May  9 12:13:22 
2014        (r265765)
+++ head/sys/dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c  Fri May  9 12:59:38 
2014        (r265766)
@@ -85,16 +85,34 @@ nf10bmac_attach_fdt(device_t dev)
        /*
         * FDT lists our resources.  For convenience we use three different
         * mappings.  We need to attach them in the oder specified in .dts:
-        * TX (size 0xc), RX (size 0xc), LOOP (size 0x4).
+        * LOOP (size 0x1f), TX (0x2f), RX (0x2f), INTR (0xf).
         */
 
+       /*
+        * LOOP memory region (this could be a general control region).
+        * 0x00: 32bit register to enable a Y-"lopback".
+        */
+        sc->nf10bmac_ctrl_rid = 0;
+        sc->nf10bmac_ctrl_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+            &sc->nf10bmac_ctrl_rid, RF_ACTIVE);
+        if (sc->nf10bmac_ctrl_res == NULL) {
+                device_printf(dev, "failed to map memory for CTRL region\n");
+                error = ENXIO;
+                goto err;
+        } 
+        if (bootverbose)
+                device_printf(sc->nf10bmac_dev, "CTRL region at mem %p-%p\n",
+                    (void *)rman_get_start(sc->nf10bmac_ctrl_res),
+                    (void *)(rman_get_start(sc->nf10bmac_ctrl_res) + 
+                    rman_get_size(sc->nf10bmac_ctrl_res)));
+
         /*
          * TX and TX metadata FIFO memory region.
          * 0x00: 32bit FIFO data,
-        * 0x04: 32bit FIFO metadata,
-         * 0x08: 32bit packet length.
+        * 0x08: 32bit FIFO metadata,
+         * 0x10: 32bit packet length.
          */
-        sc->nf10bmac_tx_mem_rid = 0;
+        sc->nf10bmac_tx_mem_rid = 1;
         sc->nf10bmac_tx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
             &sc->nf10bmac_tx_mem_rid, RF_ACTIVE);
         if (sc->nf10bmac_tx_mem_res == NULL) {
@@ -111,10 +129,10 @@ nf10bmac_attach_fdt(device_t dev)
         /*
          * RX and RXC metadata FIFO memory region.
          * 0x00: 32bit FIFO data,
-        * 0x04: 32bit FIFO metadata,
-         * 0x08: 32bit packet length.
+        * 0x08: 32bit FIFO metadata,
+         * 0x10: 32bit packet length.
          */
-        sc->nf10bmac_rx_mem_rid = 1;
+        sc->nf10bmac_rx_mem_rid = 2;
         sc->nf10bmac_rx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
             &sc->nf10bmac_rx_mem_rid, RF_ACTIVE);
         if (sc->nf10bmac_rx_mem_res == NULL) {
@@ -129,22 +147,28 @@ nf10bmac_attach_fdt(device_t dev)
                     rman_get_size(sc->nf10bmac_rx_mem_res)));
 
        /*
-        * LOOP memory region (this could be a general control region).
-        * 0x00: 32bit register to enable a Y-"lopback".
+        * Interrupt handling registers.
+        * 0x00: 32bit register to clear (and disable) the RX interrupt.
+        * 0x08: 32bit register to enable or disable the RX interrupt.
         */
-        sc->nf10bmac_mem_rid = 2;
-        sc->nf10bmac_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-            &sc->nf10bmac_mem_rid, RF_ACTIVE);
-        if (sc->nf10bmac_mem_res == NULL) {
-                device_printf(dev, "failed to map memory for CTRL region\n");
+        sc->nf10bmac_intr_rid = 3;
+        sc->nf10bmac_intr_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+            &sc->nf10bmac_intr_rid, RF_ACTIVE);
+        if (sc->nf10bmac_intr_res == NULL) {
+                device_printf(dev, "failed to map memory for INTR region\n");
                 error = ENXIO;
                 goto err;
         } 
         if (bootverbose)
-                device_printf(sc->nf10bmac_dev, "CTRL region at mem %p-%p\n",
-                    (void *)rman_get_start(sc->nf10bmac_mem_res),
-                    (void *)(rman_get_start(sc->nf10bmac_mem_res) + 
-                    rman_get_size(sc->nf10bmac_mem_res)));
+                device_printf(sc->nf10bmac_dev, "INTR region at mem %p-%p\n",
+                    (void *)rman_get_start(sc->nf10bmac_intr_res),
+                    (void *)(rman_get_start(sc->nf10bmac_intr_res) + 
+                    rman_get_size(sc->nf10bmac_intr_res)));
+
+       /* (Optional) RX and TX IRQ. */
+       sc->nf10bmac_rx_irq_rid = 0;
+       sc->nf10bmac_rx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+           &sc->nf10bmac_rx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
 
        error = nf10bmac_attach(dev);
        if (error)

Modified: head/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h
==============================================================================
--- head/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h   Fri May  9 12:13:22 
2014        (r265765)
+++ head/sys/dev/netfpga10g/nf10bmac/if_nf10bmacreg.h   Fri May  9 12:59:38 
2014        (r265766)
@@ -35,15 +35,20 @@
 
 struct nf10bmac_softc {
        struct ifnet            *nf10bmac_ifp;
+       struct resource         *nf10bmac_ctrl_res;
        struct resource         *nf10bmac_tx_mem_res;
        struct resource         *nf10bmac_rx_mem_res;
-       struct resource         *nf10bmac_mem_res;
+       struct resource         *nf10bmac_intr_res;
+       struct resource         *nf10bmac_rx_irq_res;
+       void                    *nf10bmac_rx_intrhand;
        uint8_t                 *nf10bmac_tx_buf;
        device_t                nf10bmac_dev;
        int                     nf10bmac_unit;
+       int                     nf10bmac_ctrl_rid;
        int                     nf10bmac_tx_mem_rid;
        int                     nf10bmac_rx_mem_rid;
-       int                     nf10bmac_mem_rid;
+       int                     nf10bmac_intr_rid;
+       int                     nf10bmac_rx_irq_rid;
        int                     nf10bmac_if_flags;
        uint32_t                nf10bmac_flags;
 #define        NF10BMAC_FLAGS_LINK             0x00000001
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to