changeset 84:6432998a8245

Finish the patches on the rx/tx init and wip on the actual tx
author Louis Opter <louis@lse.epitech.net>
date Mon, 09 Jul 2012 06:44:51 +0200
parents 27f0e70df342
children 5dda73e7d728
files e1000_fix_rdt_set.patch e1000_implement_the_frame_transmission_chunk.patch e1000_initialize_transmission.patch series
diffstat 4 files changed, 188 insertions(+), 327 deletions(-) [+]
line wrap: on
line diff
--- a/e1000_fix_rdt_set.patch	Sun Jul 08 10:00:25 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-# HG changeset patch
-# Parent bcab8e474b3aca4c4b326869a05d3ee69e1c82a5
-rathaxes: fix a stupid bug in e1000: the tail index for the rx descriptors ring was improperly set + couple of cosmetics
-
-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
-@@ -49,7 +49,6 @@
-     {
-         chunk   LKM::includes()
-         {
--
-             static const ${e1000::RxRing}   force_rtx_e1000_rx_ring_decl;
-         }
- 
-@@ -638,7 +637,7 @@
-             rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV);
- 
-             {
--                ${Log::info("setup_device: program receieve address done")};
-+                ${Log::info("setup_device: receive address programmed")};
-             }
- 
-             /* 2. Initialize the MTA */
-@@ -668,7 +667,7 @@
-             }
- 
-             {
--                ${Log::info("setup_device: descriptors allocated")};
-+                ${Log::info("setup_device: rx descriptors allocated")};
-             }
- 
-             /*
-@@ -716,7 +715,7 @@
- 
-             /* 6. Setup RDH/RDT */
-             rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0);
--            rtx_e1000_register_write32(hw_ctx, E1000_RDT, hw_ctx->rx_ring.size - 1);
-+            rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1);
- 
-             /* 7. Configure the buffer size, XXX: * E1000_RCTL_BSIZE_${config.rx_buffer_len} */
-             rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_2048);
--- a/e1000_implement_the_frame_transmission_chunk.patch	Sun Jul 08 10:00:25 2012 +0200
+++ b/e1000_implement_the_frame_transmission_chunk.patch	Mon Jul 09 06:44:51 2012 +0200
@@ -1,20 +1,22 @@
 # HG changeset patch
-# Parent 1a5a83776de5ecff15e42930c7741f5b4f2ada13
+# Parent 72f11dd4265bb367278f34b23ecb5afa0f7f6fb7
 rathaxes: start to queue up packets in the TX ring on the e1000 sample
 
+diff --git a/maintainers/CMakeScripts/Templates/MakefileLKM.in b/maintainers/CMakeScripts/Templates/MakefileLKM.in
+--- a/maintainers/CMakeScripts/Templates/MakefileLKM.in
++++ b/maintainers/CMakeScripts/Templates/MakefileLKM.in
+@@ -1,6 +1,6 @@
+ # Disable this "coding-style" warning (seriously, you have to compile with
+ # -pedantic to get it...)
+-EXTRA_CFLAGS	= -Wno-declaration-after-statement
++EXTRA_CFLAGS	= -Wno-declaration-after-statement -std=gnu99
+ 
+ KDIR		= /lib/modules/$(shell uname -r)/build
+ obj-m		:= @LKM_OBJECTS@
 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
-@@ -597,7 +597,7 @@
- 
-         chunk   ::CALL()
-         {
--            // this is an hack for the scope
-+            // See #10
-             (void)1;
-             {
-                 int error;
-@@ -970,4 +970,31 @@
+@@ -964,4 +964,20 @@
              }
          }
      }
@@ -23,44 +25,143 @@
 +    {
 +        chunk   ::CALL()
 +        {
++            (void)1; // Issue 10
 +            /*
 +             * Put packets on the TX ring, must return NETDEV_TX_OK or
 +             * NETDEV_TX_BUSY.
 +             */
-+            (void)1; // See #10
 +            {
 +                ${Log::info("xmit: skbuff details:")};
++                ${skb.dump_infos()};
 +            }
-+            pr_info(
-+                    "\t     len = %-5u data_len = %-5u head_len = %-5u\n"
-+                    "\tnr_frags = %u\n"
-+                    "\tgso_size = %-5u gso_segs = %-5u gso_type = %-5u\n",
-+                    ${skb}->len,
-+                    ${skb}->data_len,
-+                    skb_headlen(${skb}),
-+                    skb_shinfo(${skb})->nr_frags,
-+                    skb_shinfo(${skb})->gso_size,
-+                    skb_shinfo(${skb})->gso_segs,
-+                    skb_shinfo(${skb})->gso_type
-+            );
 +        }
 +    }
  }
 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
 --- a/rathaxes/samples/e1000/e1000.rti
 +++ b/rathaxes/samples/e1000/e1000.rti
-@@ -70,6 +70,11 @@
+@@ -109,6 +109,11 @@
          provided chunk  ::CALL();
      }
  
-+    provided sequence   e1000::xmit(Ethernet::Device, Socket::SKBuff)
++    provided sequence   xmit(Ethernet::Device, Socket::SKBuff)
 +    {
 +        provided chunk  ::CALL();
 +    }
 +
-     provided sequence   e1000::register_read32(e1000::Context, e1000::Register)
+     provided sequence   register_read32(e1000::Context, e1000::Register)
      {
          provided chunk  LKM::prototypes();
+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
+@@ -1,6 +1,51 @@
+ with Ethernet, PCI, LKM, Log
+ {
+-    template type Ethernet::Net()
++    template type   Ethernet::ProtocolId()
++    {
++        chunk LKM::prototypes()
++        {
++            static const char   *rtx_ethernet_protocol_id_to_str(unsigned short);
++        }
++
++        chunk LKM::data()
++        {
++            static const struct
++            {
++                const unsigned short    id;
++                const char              *name;
++            } rtx_ethernet_proto_table[] =
++            {
++                { ETH_P_IP,     "IPv4"  },
++                { ETH_P_IPV6,   "IPv6"  },
++                { ETH_P_ARP,    "ARP"   },
++            };
++        }
++
++        chunk LKM::code()
++        {
++            static const char   *rtx_ethernet_protocol_id_to_str(unsigned short proto_id)
++            {
++                for (int i = 0;
++                     i != sizeof(rtx_ethernet_proto_table[0]) / sizeof(rtx_ethernet_proto_table);
++                     i++)
++                    if (proto_id == rtx_ethernet_proto_table[i].id)
++                        return rtx_ethernet_proto_table[i].name;
++
++                return "Other";
++            }
++        }
++
++        chunk to_str()
++        {
++            rtx_ethernet_protocol_id_to_str(${self});
++        }
++
++        map
++        {
++        }
++    }
++
++    template type   Ethernet::AbstractDevice()
+     {
+         chunk LKM::includes()
+         {
+@@ -17,11 +62,6 @@
+         }
+     }
+ 
+-    /*
+-     * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device
+-     * from Linux. Ethernet::Device is the type that we use in the private
+-     * field of the struct net_device.
+-     */
+     template type   Ethernet::Device()
+     {
+         chunk LKM::includes()
+@@ -52,7 +92,7 @@
+             } *rtx_ethernet_dev_p;
+         }
+ 
+-        chunk ::init(Ethernet::Net net_dev, PCI::Device pci_dev)
++        chunk ::init(Ethernet::AbstractDevice net_dev, PCI::Device pci_dev)
+         {
+             ${self} = netdev_priv(${net_dev});
+             /*
+diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
+--- a/rathaxes/samples/e1000/ethernet.rti
++++ b/rathaxes/samples/e1000/ethernet.rti
+@@ -1,11 +1,28 @@
+ interface Ethernet : Socket, PCI, LKM
+ {
+-    provided type   Net
++    provided type   ProtocolId
++    {
++        chunk       LKM::prototypes();
++        chunk       LKM::data();
++        chunk       LKM::code();
++        method      ::to_str();
++    }
++
++    /*
++     * This is the abstract type used by the Kernel to represent an ethernet
++     * device.
++     */
++    provided type   AbstractDevice
+     {
+         chunk       LKM::includes();
+         chunk       ::decl();
+     }
+ 
++    /*
++     * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device
++     * from Linux. Ethernet::Device is the type that we use in the private
++     * field of the struct net_device.
++     */
+     provided type   Device
+     {
+         chunk       LKM::includes();
 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
@@ -72,3 +173,63 @@
      }
  
      LKM::init()
+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
+@@ -1,4 +1,4 @@
+-with Socket, LKM
++with Socket, LKM, Ethernet
+ {
+     template type Socket::SKBuff()
+     {
+@@ -17,6 +17,32 @@
+         {
+         }
+ 
++        chunk ::dump_infos()
++        {
++            /*
++             * We should use a Rathaxes log abstraction instead of pr_info here,
++             * but Rathaxes doesn't support functions with a variable number of
++             * arguments yet.
++             */
++            unsigned short ethernet_proto = be16_to_cpu(${self}->protocol);
++            ${cast local.ethernet_proto as Ethernet::ProtocolId};
++
++            pr_info(
++                    "\tprotocol = %#-5x (%s)\n"
++                    "\t     len = %-5u data_len = %-5u head_len = %-5u\n"
++                    "\tnr_frags = %u\n"
++                    "\tgso_size = %-5u gso_segs = %-5u gso_type = %-5u\n",
++                    ethernet_proto, "", // XXX: ${local.ethernet_proto.to_str()},
++                    ${self}->len,
++                    ${self}->data_len,
++                    skb_headlen(${self}),
++                    skb_shinfo(${self})->nr_frags,
++                    skb_shinfo(${self})->gso_size,
++                    skb_shinfo(${self})->gso_segs,
++                    skb_shinfo(${self})->gso_type
++            );
++        }
++
+         map
+         {
+             // some work may have to be done here in order
+diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti
+--- a/rathaxes/samples/e1000/socket.rti
++++ b/rathaxes/samples/e1000/socket.rti
+@@ -1,8 +1,10 @@
+ interface Socket : LKM
+ {
+-    provided type Socket::SKBuff {
+-        chunk LKM::includes();
+-        chunk ::decl();
+-        method ::init();
++    provided type Socket::SKBuff
++    {
++        chunk   LKM::includes();
++        chunk   ::decl();
++        method  ::init();
++        method  ::dump_infos();
+     }
+ }
--- a/e1000_initialize_transmission.patch	Sun Jul 08 10:00:25 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +0,0 @@
-# HG changeset patch
-# Parent e2e48ad161482555c5e87550e76cf15ef7fdbd3e
-rathaxes: initialize transmission on the e1000 sample:
-
-- This is documented in details in the sections 14.5 and 3.3 of the
-  Intel Gigabit Controller Software Developer manual.
-
-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
-@@ -34,6 +34,59 @@
-     }
- 
-     /*
-+     * This is a generic tx descriptor for the e1000. When you use TCP
-+     * Segmentation Offload (TSO) the hardware actually uses two types of
-+     * tx descriptors in its tx ring:
-+     * - context descriptors: this descriptor doesn't actually point to data to
-+     *   send but initialize the offloading engine for the data descriptor that
-+     *   follow;
-+     * - data descriptors: this descriptor points to data from the skbuffs.
-+     */
-+    template type   e1000::TxDescriptor()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            static const ${e1000::TxDescriptor} force_rtx_e1000_tx_descriptor_decl;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            typedef struct rtx_e1000_tx_descriptor
-+            {
-+                unsigned long int   /* __le64 */    buff_addr;
-+                union
-+                {
-+                    unsigned int    /* __le32 */    data;
-+                    struct
-+                    {
-+                        unsigned short /* __le16 */ length;
-+                        unsigned char               csum_offset; /* CSO */
-+                        unsigned char               cmd;
-+                    }                               fields;
-+                }                                   lower;
-+                union
-+                {
-+                    unsigned int    /* __le32 */    data;
-+                    struct
-+                    {
-+                        unsigned char               status;
-+                        unsigned char               csum_start; /* CSS */
-+                        unsigned short /* __le16 */ special;
-+                    }                               fields;
-+                }                                   upper;
-+            } *rtx_e1000_tx_descriptor_p;
-+        }
-+
-+        chunk   ::init()
-+        {
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    /*
-      * Ring of e1000::RxDescriptors and their corresponding skbuffs.
-      *
-      * - size: total size of the ring in bytes.
-@@ -73,6 +126,43 @@
-         }
-     }
- 
-+    /*
-+     * Ring of e1000::TxDescriptors, this is a bit similar to the Rx ring except
-+     * that we don't really have to manage the skbuffs themselves (they are
-+     * given to use by the kernel).
-+     *
-+     * - 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.
-+     */
-+    template type   e1000::TxRing()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            static const ${e1000::TxRing}   force_rtx_e1000_tx_ring_decl;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            struct rtx_e1000_tx_ring
-+            {
-+                unsigned int                    size;
-+                struct rtx_e1000_tx_descriptor  *base;
-+                void*   /* dma_addr_t */        dma_base;
-+            };
-+        }
-+
-+        chunk   ::init()
-+        {
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-     template type   e1000::Context()
-     {
-         chunk   LKM::includes()
-@@ -99,6 +189,7 @@
- 
-                 /* we can't use the Rathaxes type here (#8) */
-                 struct rtx_e1000_rx_ring    rx_ring;
-+                struct rtx_e1000_tx_ring    tx_ring;
-             } *rtx_e1000_ctx_p;
-         }
- 
-@@ -139,6 +230,7 @@
-                 E1000_FCT           = 0x00030, /* Flow Control Type */
-                 E1000_RCTL          = 0x00100, /* Receive Control */
-                 E1000_FCTTV         = 0x00170, /* Flow Control Transmit Timer Value */
-+                E1000_TCTL          = 0x00400, /* Transmit Control */
-                 E1000_CRCERRS       = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */
-                 E1000_RAL           = 0x05400, /* Receive Address Low */
-                 E1000_RAH           = 0x05404, /* Receive Address High */
-@@ -148,6 +240,11 @@
-                 E1000_RDLEN         = 0x02808, /* Receive Descriptor Length */
-                 E1000_RDH           = 0x02810, /* Receive Descriptor Head */
-                 E1000_RDT           = 0x02818, /* Receive Descriptor Tail */
-+                E1000_TDBAL         = 0x03800, /* Transmit Descriptor Base Address (Low 32 bits) */
-+                E1000_TDBAH         = 0x03804, /* Transmit Descriptor Base Address (High 33 bits) */
-+                E1000_TDLEN         = 0x03808, /* Transmit Descriptor Length */
-+                E1000_TDH           = 0x03810, /* Transmit Descriptor Head */
-+                E1000_TDT           = 0x03818, /* Transmit Descriptor Tail */
-             };
-         }
- 
-@@ -226,6 +323,8 @@
-                 E1000_RCTL_BSIZE_4096           = (E1000_RCTL_BSEX | (1 << 16) | (1 << 17)),
-                 E1000_RCTL_BSIZE_8192           = (E1000_RCTL_BSEX | (1 << 17)),
-                 E1000_RCTL_BSIZE_16384          = (E1000_RCTL_BSEX | (1 << 16)),
-+                E1000_TCTL_EN                   = (1 << 1),   /* Transmitter Enable */
-+                E1000_TCTL_PSP                  = (1 << 3),   /* Pad Short Packet */
-             };
-         }
- 
-@@ -728,11 +827,64 @@
-             }
- 
-             /*
-+             * Transmission initialization (section 14.5):
-+             *
-+             * 1. Allocate the transmit descriptors ring and map it to make it
-+             *    accessible by the device;
-+             * 2. Write the start address of the ring in TDBAL/TDBAH and set
-+             *    TDLEN to the size of the ring;
-+             * 3. Set the TDH/TDT indexes to the beginning and end of the ring;
-+             * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the
-+             *    transmitter.
-+             */
-+
-+            /*
-+             * XXX: at this point we must be careful to not fuck up with i, or
-+             * we are going go have surprises in `err_skbuffs_alloc`. Maybe it's
-+             * time to separate the rx and tx initialization in two functions.
-+             */
-+
-+            /* 1. Allocate the tx ring */
-+            hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base);
-+            hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096);
-+            hw_ctx->tx_ring.base = dma_alloc_coherent(
-+                    &${ctx}->pci_dev->dev,
-+                    hw_ctx->tx_ring.size,
-+                    (dma_addr_t *)&hw_ctx->tx_ring.dma_base,
-+                    GFP_KERNEL);
-+            if (!hw_ctx->rx_ring.base)
-+            {
-+                ${Log::info("cannot allocate the descriptors for the tx ring")};
-+                goto err_tx_ring_alloc;
-+            }
-+
-+            {
-+                ${Log::info("setup_device: tx descriptors allocated")};
-+            }
-+
-+            /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */
-+            rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, (dma_addr_t)hw_ctx->tx_ring.dma_base & 0xffffffff);
-+            rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, (dma_addr_t)hw_ctx->tx_ring.dma_base >> 32);
-+            rtx_e1000_register_write32(hw_ctx, E1000_TDLEN, hw_ctx->tx_ring.size);
-+
-+            /* 3. Setup TDH/TDT to zero: the queue is empty */
-+            rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0);
-+            rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0);
-+
-+            /* 4. Set TCTL.PSP and enable the transmitter */
-+            rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_PSP);
-+
-+            {
-+                ${Log::info("transmit registers configured and transmitter enabled")};
-+            }
-+
-+            /*
-              * 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;
- 
-+        err_tx_ring_alloc:
-             /*
-              * Likewise, always the same problem with error handling, we don't
-              * know where we are at in the "parent context":
-@@ -788,6 +940,15 @@
-                 ${Log::info("free_rx_tx: rx ring free'ed")};
-             }
- 
-+            /*
-+             * Free the tx ring:
-+             * - Free the descriptors array.
-+             */
-+            dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->tx_ring.size,
-+                    hw_ctx->tx_ring.base, (dma_addr_t)hw_ctx->tx_ring.dma_base);
-+            {
-+                ${Log::info("free_rx_tx: tx ring free'ed")};
-+            }
-         }
-     }
- 
-diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
---- a/rathaxes/samples/e1000/e1000.rti
-+++ b/rathaxes/samples/e1000/e1000.rti
-@@ -2,7 +2,9 @@
- {
-     provided type   e1000::Context;
-     provided type   e1000::RxDescriptor;
-+    provided type   e1000::TxDescriptor;
-     provided type   e1000::RxRing;
-+    provided type   e1000::TxRing;
- 
-     /*
-      * These two types should actually be registers definitions in the frontend:
-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
-@@ -73,6 +73,7 @@
-     Ethernet::ifname = "rtx%d";
- 
-     e1000::rx_ring_size = 256; /* Number of incoming packets we can buffer */
-+    e1000::tx_ring_size = 256; /* Mumber of buffers we can have in the tx queue */
-     /*
-      * The e1000 supports seven receive buffer sizes: 256, 512, 1024, 2048,
-      * 4096, 8192 and 16384 bytes:
--- a/series	Sun Jul 08 10:00:25 2012 +0200
+++ b/series	Mon Jul 09 06:44:51 2012 +0200
@@ -1,3 +1,1 @@
-e1000_fix_rdt_set.patch
-e1000_initialize_transmission.patch
 e1000_implement_the_frame_transmission_chunk.patch