changeset 79:f07f6c6d6cd4

WIP on RX on e1000
author Louis Opter <louis@lse.epitech.net>
date Sun, 15 Apr 2012 01:39:59 +0200
parents 501bf9cf65dc
children 0354cceee710
files e1000_initialize_reception.patch
diffstat 1 files changed, 147 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/e1000_initialize_reception.patch	Sun Mar 04 18:55:20 2012 +0100
+++ b/e1000_initialize_reception.patch	Sun Apr 15 01:39:59 2012 +0200
@@ -17,26 +17,9 @@
 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt
 --- a/rathaxes/samples/e1000/e1000.blt
 +++ b/rathaxes/samples/e1000/e1000.blt
-@@ -21,9 +21,12 @@
-              */
-             typedef struct rtx_e1000_ctx
-             {
--                int                             bars;
--                unsigned char /* __iomem */     *ioaddr;
--                int                             irq;
-+                int                         bars;
-+                unsigned char /* __iomem */ *ioaddr;
-+                int                         irq;
-+
-+                /* we can't use the Rathaxes type here (#8) */
-+                struct rtx_e1000_rx_ring    rx_ring;
-             } *rtx_e1000_ctx_p;
-         }
- 
-@@ -36,6 +39,82 @@
-         }
-     }
- 
+@@ -1,5 +1,81 @@
+ with e1000, Ethernet, Socket, PCI, LKM, Log
+ {
 +    template type   e1000::RxDescriptor()
 +    {
 +        chunk   LKM::includes()
@@ -44,6 +27,8 @@
 +            typedef int ${e1000::RxDescriptor};
 +
 +            #include <linux/types.h>
++
++            static const ${e1000::RxDescriptor} force_rtx_e1000_rx_descriptor_decl;
 +        }
 +
 +        chunk   ::decl()
@@ -69,38 +54,36 @@
 +        }
 +    }
 +
++    /*
++     * Ring of e1000::RxDescriptors and their corresponding skbuffs.
++     *
++     * - size: total size of the ring in bytes.
++     * - base: address of the ring (we can't use the typedef here until we get
++     *   CNorm unstrict);
++     * - dma_base: (physical) address of the ring where the device can access
++     *   the different descriptors;
++     * - skbuffs: array of the skbuffs associated with each descriptor;
++     * - dma_skbuffs: (physical) address of each skbuff where the device can
++     *   write the received packets;
++     */
 +    template type   e1000::RxRing()
 +    {
 +        chunk   LKM::includes()
 +        {
 +            typedef int ${e1000::RxRing};
++
++            static const ${e1000::RxRing}   force_rtx_e1000_rx_ring_decl;
 +        }
 +
 +        chunk   ::decl()
 +        {
-+            /*
-+             * - size: total size of the ring in bytes.
-+             * - base: address of the ring;
-+             * - dma_base: (physical) address of the ring where the device
-+             *   can access it;
-+             * - skbuffs: array of the skbuffs associated with
-+             *   each descriptor;
-+             * - dma_skbuffs: (physical) address of each skbuff
-+             *   where the device can write the received
-+             *   packets;
-+             */
 +            struct rtx_e1000_rx_ring
 +            {
-+                unsigned int                	size;
-+                /*
-+                 * we can't use the typedef here because will not understand it
-+                 * in __std__ mode
-+                 */
-+                struct rtx_e1000_rx_descriptor	*base;
-+                void                        	*dma_base;
-+
-+                struct sk_buff              *skbuffs[256 /* ${config.rx_ring_size} */];
-+                void                        *dma_skbuffs[256 /* ${config.rx_ring_size} */];
++                unsigned int                    size;
++                struct rtx_e1000_rx_descriptor  *base;
++                void*   /* dma_addr_t */        dma_base;
++                struct sk_buff                  *skbuffs[256 /* ${config.rx_ring_size} */];
++                void*   /* dma_addr_t */        dma_skbuffs[256 /* ${config.rx_ring_size} */];
 +            };
 +        }
 +
@@ -113,10 +96,34 @@
 +        }
 +    }
 +
-     template type   e1000::Register()
+     template type   e1000::Context()
      {
          chunk   LKM::includes()
-@@ -64,6 +143,9 @@
+@@ -21,9 +97,12 @@
+              */
+             typedef struct rtx_e1000_ctx
+             {
+-                int                             bars;
+-                unsigned char /* __iomem */     *ioaddr;
+-                int                             irq;
++                int                         bars;
++                unsigned char /* __iomem */ *ioaddr;
++                int                         irq;
++
++                /* we can't use the Rathaxes type here (#8) */
++                struct rtx_e1000_rx_ring    rx_ring;
+             } *rtx_e1000_ctx_p;
+         }
+ 
+@@ -34,6 +113,7 @@
+         map
+         {
+         }
++
+     }
+ 
+     template type   e1000::Register()
+@@ -64,6 +144,9 @@
                  E1000_FCT           = 0x00030, /* Flow Control Type */
                  E1000_FCTTV         = 0x00170, /* Flow Control Transmit Timer Value */
                  E1000_CRCERRS       = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */
@@ -126,7 +133,7 @@
              };
          }
  
-@@ -132,7 +214,8 @@
+@@ -132,7 +215,8 @@
                  E1000_INTR_RXDMT0               = 0x00000010, /* rx desc min. threshold (0) */
                  E1000_INTR_RXO                  = 0x00000040, /* rx overrun */
                  E1000_INTR_RXT0                 = 0x00000080, /* rx timer intr (ring 0) */
@@ -136,9 +143,12 @@
              };
          }
  
-@@ -458,14 +541,24 @@
+@@ -457,15 +541,27 @@
+     {
          chunk  ::CALL()
          {
++            typedef unsigned long int   dma_addr_t;
++
              /*
 -             * This is documented in the Intel Gigabit Ethernet Controller
 -             * Software Developper manual.
@@ -163,7 +173,7 @@
               * "General Configuration" (section 14.3):
               *
               * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection &
-@@ -478,22 +571,111 @@
+@@ -478,22 +574,152 @@
               * - Finally, initialize all the statistic registers from
               *   E1000_CRCERRS to E1000_TSCTFC.
               */
@@ -193,18 +203,24 @@
 -                rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_CRCERRS + i * 4, 0);
 +                rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + i * 4, 0);
 +
++            //${Log::info("setup_device: general configuration done")};
++
 +            /*
-+             * Receive initialization
++             * Receive initialization:
 +             *
-+             * - Program the receive address, in RAL/RAH;
-+             * - Initialize the Multicast Table Array;
-+             * - Program the interrupt mask register (done in
-+             *   e1000::activate_device_interruption);
-+             * - Allocate the receive descriptor ring and map it to make it
-+             *   accessible by the device.
++             * 1. Program the receive address, in RAL/RAH;
++             * 2. Initialize the Multicast Table Array;
++             * 3. Program the interrupt mask register (done in
++             *    e1000::activate_device_interruption);
++             * 4. Allocate the receive descriptor ring and map it to make it
++             *    accessible by the device.
++             *
++             * The ugly casts in here are caused by the lack of CNorm unstrict.
 +             */
 +
-+             /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */
++            /* 1. Program the receive address */
++
++            /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */
 +            rtx_e1000_register_write32(hw_ctx, E1000_RAL,
 +                    *(unsigned int *)(${ctx}->net_dev->dev_addr));
 +            /*
@@ -215,53 +231,86 @@
 +                    *(unsigned short *)(&${ctx}->net_dev->dev_addr[4]));
 +            rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV);
 +
++            //${Log::info("setup_device: program receieve address done")};
++
++            /* 2. Initialize the MTA */
++
 +            i = 0; /* CNorm workaround, the init part of for isn't generated */
 +            for (i = 0; i != 128; ++i)
 +                rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0);
 +
++            //${Log::info("setup_device: MTA init done")};
++
++            /* 4. Setup the receive descriptor ring */
++
++            /* Allocate the descriptors */
 +            hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base);
 +            hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096);
-+            hw_ctx->rx_ring.base = dma_alloc_coherent(&${ctx}->pci_dev->dev,
-+                    hw_ctx->rx_ring.size, &hw_ctx->rx_ring.dma_base, GFP_KERNEL);
-+            if (!hw->ctx->rx_ring.base)
++            hw_ctx->rx_ring.base = dma_alloc_coherent(
++                    &${ctx}->pci_dev->dev,
++                    hw_ctx->rx_ring.size,
++                    (dma_addr_t *)&hw_ctx->rx_ring.dma_base,
++                    GFP_KERNEL);
++            if (!hw_ctx->rx_ring.base)
 +            {
-+                ${Log::info("cannot allocate the descriptors for the Rx ring")};
++                ${Log::info("cannot allocate the descriptors for the rx ring")};
 +                goto err_rx_ring_alloc;
 +            }
 +
++            //${Log::info("setup_device: descriptors allocated")};
++
++            /*
++             * Allocate the skbuffs, map them for DMA, and write their address
++             * in the corresponding descriptor.
++             */
 +            i = 0;
 +            for (i = 0; i != ${config.rx_ring_size}; ++i)
 +            {
-+                hw_ctx->rx_ring.skbuffs[i] = netdev_allock_skb(${ctx}->net_device,
++                hw_ctx->rx_ring.skbuffs[i] = netdev_alloc_skb(
++                        ${ctx}->net_dev,
 +                        ${config.rx_buffer_len});
 +                if (!hw_ctx->rx_ring.skbuffs[i])
 +                {
-+                    ${Log::info("cannot allocate a skbuff for the Rx ring")};
++                    ${Log::info("cannot allocate a skbuff for the rx ring")};
 +                    goto err_skbuffs_alloc;
 +                }
-+                hw_ctx->rx_ring.dma_skbuffs[i] = dma_map_single(&${ctx}->pci_dev->dev,
++                hw_ctx->rx_ring.dma_skbuffs[i] = (void *)dma_map_single(
++                        &${ctx}->pci_dev->dev,
 +                        hw_ctx->rx_ring.skbuffs[i]->data,
 +                        ${config.rx_buffer_len},
 +                        DMA_FROM_DEVICE);
-+                if (dma_mapping_error(&${ctx}->pci_dev->dev,
-+                            hw_ctx->rx_ring.dma_skbuffs[i]))
++                /*
++                 * Either this fails because, when compiling with gcc because
++                 * the last argument is not of the correct type (dma_addr_t).
++                 * Or it fails because of the lack of CNorm Unstrict.
++                 */
++                if (dma_mapping_error(&${ctx}->pci_dev->dev, (dma_addr_t)hw_ctx->rx_ring.dma_skbuffs[i]))
 +                {
-+                    ${Log::info("cannot dma-map a skbuff for the Rx ring")};
++                    ${Log::info("cannot dma-map a skbuff for the rx ring")};
 +                    goto err_skbuffs_map;
 +                }
-+                hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(hw_ctx->rx_ring.dma_skbuffs[i]);
++                hw_ctx->rx_ring.base[i].buff_addr = (unsigned long int)cpu_to_le64(
++                        hw_ctx->rx_ring.dma_skbuffs[i]);
 +            }
 +
++            //${Log::info("setup_device: skbuffs allocated")};
++
 +            /*
-+             * Always the same problem with error handling, we don't know where
-+             * we are at in the "parent context":
++             * XXX: We can't return here since we are not in a function but in
++             * a chunk of code (injected in a function).
 +             */
++            goto ok;
 +
++            /*
++             * Likewise, always the same problem with error handling, we don't
++             * know where we are at in the "parent context":
++             */
 +        err_skbuffs_alloc:
 +            while (i--)
 +            {
-+                dma_unmap_single(&${ctx}->pci_dev->dev,
-+                        hw_ctx->rx_ring.dma_skbuffs[i],
++                dma_unmap_single(
++                        &${ctx}->pci_dev->dev,
++                        (dma_addr_t)hw_ctx->rx_ring.dma_skbuffs[i],
 +                        ${config.rx_buffer_len},
 +                        DMA_FROM_DEVICE);
 +        err_skbuffs_map:
@@ -269,9 +318,11 @@
 +            }
 +
 +            dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->rx_ring.size,
-+                    hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
++                    hw_ctx->rx_ring.base, (dma_addr_t)hw_ctx->rx_ring.dma_base);
 +        err_rx_ring_alloc:
 +            return -ENOMEM;
++
++        ok:
 +        }
 +    }
 +
@@ -311,15 +362,24 @@
 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt
 --- a/rathaxes/samples/e1000/ethernet.blt
 +++ b/rathaxes/samples/e1000/ethernet.blt
-@@ -105,7 +105,7 @@
+@@ -64,7 +64,6 @@
+             static int  rtx_ethernet_open(struct net_device *dev)
+             {
+                 struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev);
+-                struct rtx_e1000_ctx* ctx = &rtx_ether_dev->hw_ctx;
+ 
+                 ${cast local.rtx_ether_dev as Ethernet::Device};
+                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
+@@ -105,8 +104,7 @@
          {
              static int  rtx_ethernet_close(struct net_device *dev)
              {
 -                struct rtx_ethernet_dev* rtx_ether_dev =  netdev_priv(dev);
+-                struct rtx_e1000_ctx* ctx = &rtx_ether_dev->hw_ctx;
 +                struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev);
-                 struct rtx_e1000_ctx* ctx = &rtx_ether_dev->hw_ctx;
  
                  ${cast local.rtx_ether_dev as Ethernet::Device};
+                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx
 --- a/rathaxes/samples/e1000/lkm.rtx
 +++ b/rathaxes/samples/e1000/lkm.rtx
@@ -353,3 +413,18 @@
 +     */
 +    e1000::rx_buffer_len = 2048;
  }
+diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt
+--- a/rathaxes/samples/e1000/socket.blt
++++ b/rathaxes/samples/e1000/socket.blt
+@@ -4,7 +4,11 @@
+     {
+         chunk LKM::includes()
+         {
++            typedef int ${Socket::SKBuff};
++
+             #include <linux/skbuff.h>
++
++            static const ${Socket::SKBuff} force_rtx_lnux_skbuf_decl;
+         }
+ 
+         chunk ::decl()