# HG changeset patch
# Parent ead0d8be18437dcd68451112be0652dfdec884b5
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
@@ -150,17 +150,10 @@
                 /* 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(
-                        ${rtx_ether_ctx.device},
-                        hw_ctx->rx_ring.size,
-                        &hw_ctx->rx_ring.dma_base,
-                        GFP_KERNEL);
-                /* XXX
-                 * The first arg is recognized as Ethernet::Device instead of
-                 * Device::AbstractDevice.
-                 */
                 hw_ctx->rx_ring.base = ${DMA::alloc_coherent(
-                    rtx_ether_ctx.device, local.hw_ctx.rx_ring.size, local.hw_ctx.rx_ring.dma_base.dma_handle
+                    rtx_ether_ctx.device,
+                    local.hw_ctx.rx_ring.size,
+                    local.hw_ctx.rx_ring.dma_base.dma_handle
                 )};
                 if (!hw_ctx->rx_ring.base)
                 {
@@ -176,19 +169,13 @@
                  */
                 for (i = 0; i != ${config.rx_ring_size}; ++i)
                 {
-                    // XXX #46: ${Socket::SKBuff.ref} skbuff = ${rtx_ether_ctx.net_device.alloc_rx_skbuff(config.rx_buffer_len)};
-                    ${Socket::AbstractSKBuff.ref} k_sk_buff = (${Socket::AbstractSKBuff.ref})netdev_alloc_skb(
-                        ${rtx_ether_ctx.net_device.k_net_dev}, ${config.rx_buffer_len}
-                    );
-                    if (!k_sk_buff)
+                    ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i];
+                    // XXX #46: ${rtx_ether_ctx.init_rx_skbuff(local.skbuff, config.rx_buffer_len)};
+                    if (rtx_ethernet_init_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len}))
                     {
                         ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")};
                         goto err_skbuffs_alloc;
                     }
-                    ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i];
-                    // XXX breaks rtxGen: ${local.skbuff.init(local.k_sk_buff)};
-                    skbuff->skbuff = k_sk_buff;
-                    *(dma_addr_t *)&(skbuff->dma_handle) = 0;
                     // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)};
                     if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE))
                     {
@@ -199,7 +186,7 @@
                 }
 
                 // ${Log::info("adapter_init_rx: skbuffs allocated};
-                pr_info("adapter_init_rx: skbuffs allocated, headlen=%d", skb_headlen((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff));
+                pr_info("rtx_e1k: adapter_init_rx: skbuffs allocated, headlen=%d", skb_headlen((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i - 1].skbuff));
 
                 /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */
                 rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff);
@@ -565,7 +552,7 @@
         map
         {
             rx_ring: ((${self})->rx_ring);
-            //tx_ring: ((${self})->tx_ring);
+            //tx_ring: ((${self})->tx_ring); XXX Circular dep with Context
         }
     }
 
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
@@ -48,6 +48,8 @@
         chunk       Ethernet::adapter_setup(Ethernet::Device);
 
         attribute   RxRing.scalar   rx_ring;
+        /* XXX: circular dependency with Contex: */
+        //attribute   TxRing.scalar   tx_ring;
     }
 
     provided type   TxRing
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
@@ -95,6 +95,24 @@
             #include <linux/etherdevice.h>
         }
 
+        chunk LKM::prototypes()
+        {
+            static int rtx_ethernet_alloc_rx_skbuff(${Ethernet::Device.ref}, ${Socket::SKBuff.ref}, ${Builtin::number});
+        }
+
+        chunk LKM::code()
+        {
+            static int rtx_ethernet_alloc_rx_skbuff(${Ethernet::Device.ref} self, ${Socket::SKBuff.ref} sk_buff, ${Builtin::number} size)
+            {
+                ${Socket::AbstractSKBuff} k_sk_buff = netdev_alloc_skb(${local.self.net_device.k_net_dev}, ${local.size});
+                if (${local.k_sk_buff) {
+                    ${local.sk_buff.init(local.k_sk_buff, local.size)};
+                    return 0;
+                }
+                return 1;
+            }
+        }
+
         /* XXX: if the first arg is not called rtx_net_dev, it breaks. */
         method init(Ethernet::AbstractDevice rtx_net_dev, PCI::AbstractDevice pci_dev)
         {
@@ -107,9 +125,9 @@
             ${self}->net_dev = ${rtx_net_dev};
         }
 
-        method alloc_rx_skbuff(Builtin::number size)
+        method alloc_rx_skbuff(Socket::SKBuff sk_buff, Builtin::number size)
         {
-            (${Socket::Skbuff.ref})netdev_alloc_skb(${self}, ${size});
+            rtx_ethernet_alloc_rx_skbuff(${self}, ${sk_buff}, ${size});
         }
 
         map
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
@@ -33,7 +33,11 @@
         pointcut    Ethernet::HardwareContext();
 
         method      init(Ethernet::AbstractDevice, PCI::AbstractDevice);
-        method      alloc_rx_skbuff(Builtin::number); /* -> Socket::Skbuff.ref */
+        /*
+         * Alloc (the AbstractSKBuff inside) the given SKBuff and initialize
+         * the SKBuff, return 1 if the allocation failed, 0 on success.
+         */
+        method      alloc_rx_skbuff(Socket::SKBuff, Builtin::number);
 
         attribute   Device::AbstractDevice.ref      device;
         attribute   PCI::AbstractDevice.ref         pci_device;
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
@@ -24,6 +24,7 @@
         {
             ${Socket::AbstractSKBuff.ref}       skbuff;
             ${DMA::AbstractDMAHandle.scalar}    dma_handle;
+            unsigned int                        size;
         }
 
         chunk   LKM::prototypes()
@@ -69,8 +70,13 @@
             {
                 WARN_ON(!${local.self.sk_buff});
                 WARN_ON(${local.self.dma_handle});
+                /*
+                 * TODO: we don't support skbuffs with paged data yet (see also
+                 * http://vger.kernel.org/~davem/skb_data.html).
+                 */
+                WARN_ON(skb_is_nonlinear(${local.self.sk_buff.k_sk_buff}));
 
-                unsigned int len = skb_headlen(${local.self.sk_buff.k_sk_buff});
+                unsigned int len = ${local.self.size};
                 ${cast local.len as Builtin::number};
                 ${local.self.dma_handle} = ${DMA::map(local.dev, local.self.sk_buff.k_sk_buff, local.len, local.direction)};
                 int err = ${DMA::mapping_error(local.dev, local.self.dma_handle)};
@@ -87,10 +93,11 @@
                                                          ${DMA::DMADirection} direction)
             {
                 WARN_ON(!${local.self.sk_buff});
+                WARN_ON(skb_is_nonlinear(${local.self.sk_buff.k_sk_buff});
 
                 if (${local.self.dma_handle})
                 {
-                    unsigned int len = skb_headlen(${local.self.sk_buff.k_sk_buff});
+                    unsigned int len = ${local.self.size};
                     ${cast local.len as Builtin::number};
                     ${DMA::unmap(local.dev, local.self.dma_handle, local.len, local.direction)};
                     ${local.self.dma_handle} = 0;
@@ -105,13 +112,14 @@
          * correct C variable from Ethernet::send() (so I named it as the C
          * variable I needed)
          */
-        method init(Socket::AbstractSKBuff kernel_skb)
+        method  init(Socket::AbstractSKBuff kernel_skb, Builtin::number size)
         {
             ${self.sk_buff} = ${kernel_skb};
+            ${self.size} = ${size};
             ${self.dma_handle} = 0;
         }
 
-        method dump_infos()
+        method  dump_infos()
         {
             rtx_socket_skbuff_dump_infos(${self});
         }
@@ -149,6 +157,7 @@
             // would yield to a struct type which you can't assign directly;
             // but maybe doing the ->data in that case would be acceptable).
             dma_handle: (*((dma_addr_t *)&(${self})->dma_handle));
+            size: (${self})->size;
         }
     }
 }
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
@@ -13,7 +13,7 @@
         chunk   LKM::prototypes();
         chunk   LKM::code();
         decl    data_types();
-        method  init(Socket::AbstractSKBuff);
+        method  init(Socket::AbstractSKBuff, Builtin::number);
         method  dump_infos();
         /*
          * map_to and map_from return a non-zero value on failure (which
@@ -26,5 +26,6 @@
 
         attribute   Socket::AbstractSKBuff.ref      sk_buff;
         attribute   DMA::AbstractDMAHandle.scalar   dma_handle;
+        attribute   Builtin::number.scalar          size;
     }
 }
