view rathaxes_change_the_abstract_type_notation_in_the_e1000_sample.patch @ 105:fb20f01ea997

Wip, note: the interrupt handler refactoring patch is broken, I have to find the fix from the abstract type notation patch
author Louis Opter <louis@lse.epita.fr>
date Fri, 22 Mar 2013 00:25:52 -0700
parents c4c33ac02b93
children 976a4b87803f
line wrap: on
line source

# HG changeset patch
# Parent 1fa9b24e6012b2d53f1a84d4606cf3b6b9685fef
rathaxes: change the abstract type notation in the e1000 sample

Starting with ra24db32bf134 Rathaxes types are generated differently: you
don't define entire structures anymore, but only the fields. And the
compiler generate a typedef'ed structure on top of it.

This works fine, except for "abstract types" (the types defined by —and
used to interact with— the kernel). We need to define these types as
Rathaxes types to interact with them, in Rathaxes, but with
ra24db32bf134 it means that we loose (hide) the original type from the
kernel, making it very difficult to use "abstract types" with the
kernels APIs.

For example, here the hypothetical generated struct for the abstract
type "struct net_device" from Linux would be:

typedef struct {
    struct net_device   data;
} rtx_GeneratedType;

And here is how we have to use it:

rtx_GeneratedType *my_struct;
kernel_api_function(&my_struct->data);

This &my_struct->data is actually always a nop, but it's confusing and
hard to understand.

This changeset changes the notation to:

rtx_GeneratedType *my_struct;
kernel_api_function((struct net_device *)my_struct);

Which is, I believe, more intuitive and coherent with how you would
initialize the my_struct pointer here with a return value from the
kernel (i.e: with a cast into rtx_GeneratedType *).

diff --git a/rathaxes/samples/e1000/device.blt b/rathaxes/samples/e1000/device.blt
--- a/rathaxes/samples/e1000/device.blt
+++ b/rathaxes/samples/e1000/device.blt
@@ -18,7 +18,7 @@
 
         map
         {
-            data:   ${self}->data;
+            k_device: ((struct device *)${self});
         }
     }
 }
diff --git a/rathaxes/samples/e1000/device.rti b/rathaxes/samples/e1000/device.rti
--- a/rathaxes/samples/e1000/device.rti
+++ b/rathaxes/samples/e1000/device.rti
@@ -5,6 +5,6 @@
         decl        data_types();
         chunk       LKM::includes();
         method      init();
-        attribute   Builtin::symbol data;
+        attribute   Builtin::symbol k_device;
     }
 }
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
@@ -171,13 +171,17 @@
 
             static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
             {
-                ${Socket::AbstractSKBuff} *abs_skb = skb->skbuff;
-                ${cast local.abs_skb as Socket::AbstractSKBuff};
-                return skb_is_gso(&${local.abs_skb.data}) || ${local.abs_skb.data}.ip_summed == CHECKSUM_PARTIAL;
+                /* XXX We can't use ${skb} here because it's a pointer */
+                ${Socket::AbstractSKBuff} *k_skb = skb->skbuff;
+                ${cast local.k_skb as Socket::AbstractSKBuff};
+                return skb_is_gso(${local.k_skb.k_sk_buff}) || ${local.k_skb.k_sk_buff}->ip_summed == CHECKSUM_PARTIAL;
             }
 
             static void         rtx_e1000_tx_ring_put(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
             {
+                /* XXX We can't use ${skb} here because it's a pointer */
+                ${Socket::AbstractSKBuff} *k_skb = skb->skbuff;
+                ${cast local.k_skb as Socket::AbstractSKBuff};
                 WARN_ON(!skb);
 
                 /*
@@ -188,17 +192,15 @@
                  * code shouldn't be aware of it and use something more
                  * abstract.
                  */
-                ${Socket::AbstractSKBuff} *abs_skb = skb->skbuff;
-                ${cast local.abs_skb as Socket::AbstractSKBuff};
                 ${e1000::TxDescriptor} *tx_desc = &self->base[self->tail];
                 tx_desc->lower.data = cpu_to_le32(
                         E1000_TXD_CMD_EOP  |
                         E1000_TXD_CMD_IFCS |
                         E1000_TXD_CMD_RS   |
-                        skb_headlen(&${local.abs_skb.data}));
+                        skb_headlen(${local.k_skb.k_sk_buff}));
                 tx_desc->upper.data = 0;
                 tx_desc->buff_addr = cpu_to_le64(skb->dma_handle);
-                memcpy(&self->skbuffs[self->tail], skb, sizeof(*skb));
+                memcpy(&self->skbuffs[self->tail], ${local.k_skb.k_sk_buff}, sizeof(*${local.k_skb.k_sk_buff}));
                 self->tail = (self->tail + 1) % ${config.tx_ring_size};
             }
 
@@ -733,7 +735,7 @@
             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},
+                    ${rtx_ether_ctx.device},
                     hw_ctx->rx_ring.size,
                     &hw_ctx->rx_ring.dma_base,
                     GFP_KERNEL);
@@ -751,12 +753,10 @@
              * Allocate the skbuffs, map them for DMA, and write their address
              * in the corresponding descriptor.
              */
-            ${Ethernet::AbstractDevice} *rtx_ether_dev = ${rtx_ether_ctx.net_device};
-            ${cast local.rtx_ether_dev as Ethernet::AbstractDevice};
             for (i = 0; i != ${config.rx_ring_size}; ++i)
             {
-                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)  netdev_alloc_skb(
-                        &${rtx_ether_dev.netdev},
+                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb(
+                        ${rtx_ether_ctx.net_device.k_net_dev}, /* XXX: .k_net_dev isn't expanded here */
                         ${config.rx_buffer_len});
                 if (!hw_ctx->rx_ring.skbuffs[i].skbuff)
                 {
@@ -764,11 +764,11 @@
                     goto err_skbuffs_alloc;
                 }
                 hw_ctx->rx_ring.skbuffs[i].dma_handle = dma_map_single(
-                        &${rtx_ether_ctx.device},
-                        &hw_ctx->rx_ring.skbuffs[i].skbuff->data,
+                        ${rtx_ether_ctx.device},
+                        (struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff, /* XXX leaking cast */
                         ${config.rx_buffer_len},
                         DMA_FROM_DEVICE);
-                int dma_error = dma_mapping_error(&${rtx_ether_ctx.device},
+                int dma_error = dma_mapping_error(${rtx_ether_ctx.device},
                         hw_ctx->rx_ring.skbuffs[i].dma_handle);
                 if (dma_error)
                 {
@@ -820,7 +820,7 @@
             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(
-                    &${rtx_ether_ctx.device},
+                    ${rtx_ether_ctx.device},
                     hw_ctx->tx_ring.size,
                     &hw_ctx->tx_ring.dma_base,
                     GFP_KERNEL);
@@ -863,15 +863,16 @@
             while (i--)
             {
                 dma_unmap_single(
-                        &${rtx_ether_ctx.device},
+                        ${rtx_ether_ctx.device},
                         hw_ctx->rx_ring.skbuffs[i].dma_handle,
                         ${config.rx_buffer_len},
                         DMA_FROM_DEVICE);
         err_skbuffs_map:
-                dev_kfree_skb(&hw_ctx->rx_ring.skbuffs[i].skbuff->data);
+                /* XXX leaking cast: */
+                dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff);
             }
 
-            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
+            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
                     hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
         err_rx_ring_alloc:
             return -ENOMEM;
@@ -889,8 +890,13 @@
     {
         chunk   ::CALL()
         {
-            ${e1000::Context} *hw_ctx;
-            hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+            /*
+             * XXX: Not generated if named "hw_ctx" (which is funny because
+             * it's used and works in the template right above this one):
+             */
+            ${e1000::Context} *hw_ctx_;
+            ${cast local.hw_ctx_ as e1000::Context};
+            hw_ctx_ = &${rtx_ether_ctx}->hw_ctx;
 
             /*
              * Free the rx ring:
@@ -900,22 +906,23 @@
             for (int i = 0; i != ${config.rx_ring_size}; ++i)
             {
                 dma_unmap_single(
-                        &${rtx_ether_ctx.device},
-                        (dma_addr_t)hw_ctx->rx_ring.skbuffs[i].dma_handle,
+                        ${rtx_ether_ctx.device},
+                        (dma_addr_t)hw_ctx_->rx_ring.skbuffs[i].dma_handle,
                         ${config.rx_buffer_len},
                         DMA_FROM_DEVICE);
-                dev_kfree_skb(&hw_ctx->rx_ring.skbuffs[i].skbuff->data);
+                /* XXX Go through the rtx types (Socket::SKBuff, AbstractSKBuff) */
+                dev_kfree_skb(hw_ctx_->rx_ring.skbuffs[i].skbuff);
             }
-            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
-                    hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
+            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->rx_ring.size,
+                    hw_ctx_->rx_ring.base, hw_ctx_->rx_ring.dma_base);
             ${Log::info("free_rx_tx: rx ring free'ed")};
 
             /*
              * Free the tx ring:
              * - Free the descriptors array.
              */
-            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->tx_ring.size,
-                    hw_ctx->tx_ring.base, hw_ctx->tx_ring.dma_base);
+            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->tx_ring.size,
+                    hw_ctx_->tx_ring.base, hw_ctx_->tx_ring.dma_base);
             ${Log::info("free_rx_tx: tx ring free'ed")};
         }
     }
@@ -973,13 +980,13 @@
             ${local.skb.init(kernel_skb)};
             hw_ctx = &${rtx_ether_ctx}->hw_ctx;
             tx_ring = &hw_ctx->tx_ring;
-            devp = (${Device::AbstractDevice}*) &${rtx_ether_ctx.device};
+            devp = (${Device::AbstractDevice}*)${rtx_ether_ctx.device};
 
             ${Log::info("xmit: skbuff details:")};
             /*
-             * skb is not expand on the bound C variable (should be rtx_skbuff),
-             * which is funny because it works for the sequence template call
-             * right after.
+             * skb does not expand on the bound C variable (should be
+             * rtx_skbuff), which is funny because it works for the
+             * sequence template call right after.
              */
             /*
              * XXX: doesn't work (I tried to pass self explicitely too):
@@ -1012,8 +1019,8 @@
 
             /* 2. Map the data */
 
-            /* XXX: ${local.skb.map_to(local.devp)}; */
-            if (rtx_socket_skbuff_map(&skb, &${devp.data}, DMA_TO_DEVICE))
+            /* XXX: ${local.skb.map_to(devp.k_device)}; */
+            if (rtx_socket_skbuff_map(&skb, ${devp.k_device}, DMA_TO_DEVICE))
             {
                 ${Log::info("xmit: can't DMA map a SKbuff")};
                 goto err_skb_map_to;
@@ -1032,7 +1039,7 @@
         err_offload:
         err_skb_map_to:
             /* XXX: ${local.skb.unmap_to_and_free(local.dev)}; */
-            rtx_socket_skbuff_unmap_and_free(&skb, &${devp.data}, DMA_TO_DEVICE);
+            rtx_socket_skbuff_unmap_and_free(&skb, ${devp.k_device}, DMA_TO_DEVICE);
             return NETDEV_TX_OK;
         }
     }
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
@@ -51,7 +51,7 @@
     {
         decl  data_types()
         {
-            struct net_device ndev;
+            struct net_device   data;
         }
 
         chunk LKM::includes()
@@ -59,9 +59,15 @@
             #include <linux/netdevice.h>
         }
 
+        method  init(Builtin::symbol dev)
+        {
+            ${self} = (${Ethernet::AbstractDevice} *)${dev};
+        }
+
         map
         {
-            netdev:   ${self}->ndev;
+            k_net_dev: ((struct net_device *)${self});
+            rtx_ether_ctx: netdev_priv((struct net_device *)${self});
         }
     }
 
@@ -88,25 +94,33 @@
             #include <linux/etherdevice.h>
         }
 
-        method init(Ethernet::AbstractDevice net_dev, PCI::AbstractDevice pci_dev)
+        /* XXX: if the first arg is not called rtx_net_dev, it breaks. */
+        method init(Ethernet::AbstractDevice rtx_net_dev, PCI::AbstractDevice pci_dev)
         {
-            ${self} = netdev_priv(&${net_dev.netdev});
+            ${self} = ${rtx_net_dev.rtx_ether_ctx}; 
             /*
              * We can use -> because we know that ${self} will be always a
              * pointer, but the ambiguity sucks.
              */
             ${self}->pci_dev = ${pci_dev};
-            ${self}->net_dev = ${net_dev};
+            ${self}->net_dev = ${rtx_net_dev};
         }
 
         map
         {
-            device: ${self}->pci_dev->data.dev;
+            /*
+             * XXX: I'd like to be able to do things like:
+             * device: ${self.pci_dev.k_pci_dev}->dev;
+             *
+             * Also, using ${PCI::AbstractDevice} instead of directly struct
+             * pci_dev doesn't work.
+             */
+            device: (&((struct pci_dev *)(${self})->pci_dev)->dev);
             pci_device: ${self}->pci_dev;
             net_device: ${self}->net_dev;
-            perm_addr: ${self}->net_dev->ndev.perm_addr;
-            dev_addr: ${self}->net_dev->ndev.dev_addr;
-            irq: ${self}->pci_dev->data.irq;
+            perm_addr: ((struct net_device *)(${self})->net_dev)->perm_addr;
+            dev_addr: ((struct net_device *)(${self})->net_dev)->dev_addr;
+            irq: ((struct pci_dev *)(${self})->pci_dev)->irq;
         }
     }
 
@@ -126,8 +140,17 @@
         {
             static int  rtx_ethernet_open(struct net_device *dev)
             {
-                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
+                /*
+                 * XXX The casts are here because the compiler doesn't resolve
+                 * "enclosed" type (e.g: local.var.enclosed) correctly.
+                 */
+                ${Ethernet::AbstractDevice} *rtx_net_dev;
+                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
+                { /* XXX: I end up with a placeholder if I don't open a scope */
+                    ${local.rtx_net_dev.init(local.dev)};
+                }
 
+                ${Ethernet::Device} *rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
                 ${cast local.rtx_ether_ctx as Ethernet::Device};
 
                 int error;
@@ -187,8 +210,13 @@
         {
             static int  rtx_ethernet_close(struct net_device *dev)
             {
-                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
+                ${Ethernet::AbstractDevice} *rtx_net_dev;
+                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
+                { /* XXX: I end up with a placeholder if I don't open a scope */
+                    ${local.rtx_net_dev.init(local.dev)};
+                }
 
+                ${Ethernet::Device} *rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
                 ${cast local.rtx_ether_ctx as Ethernet::Device};
 
                 /* TODO: change this pointcut into a pointcut/adapter/callback: */
@@ -221,9 +249,13 @@
         {
             static enum irqreturn   rtx_ethernet_interrupt_handler(int irq, void *dev_id)
             {
-                ${Ethernet::Device} *rtx_ether_ctx = dev_id;
+                ${Ethernet::AbstractDevice} *rtx_net_dev = dev_id;
+                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
 
+                ${Ethernet::Device} *rtx_ether_ctx;
                 ${cast local.rtx_ether_ctx as Ethernet::Device};
+                rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
+
                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
 
                 return IRQ_NONE;
@@ -253,23 +285,26 @@
          */
         chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev)
         {
+            ${Ethernet::AbstractDevice} *rtx_net_dev;
             ${Ethernet::Device} *rtx_ether_ctx;
-            ${Ethernet::AbstractDevice} *net_dev;
-            ${cast local.net_dev as Ethernet::AbstractDevice};
+            ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
 
-            net_dev = (${Ethernet::AbstractDevice}*) alloc_etherdev(sizeof(*rtx_ether_ctx));
-            if (!net_dev)
+            /* Cast the result back into our "transparent wrapper" type */
+            rtx_net_dev = (${Ethernet::AbstractDevice}*)alloc_etherdev(sizeof(*rtx_ether_ctx));
+            if (!rtx_net_dev)
             {
                 ${Log::info("cannot allocate the ethernet device context")};
                 error = -ENOMEM;
                 goto fail;
             }
-            SET_NETDEV_DEV(&${local.net_dev.netdev}, ${rtx_pci_dev.device});
-            strlcpy(${local.net_dev.netdev}.name, ${config.ifname}, sizeof(${local.net_dev.netdev}.name));
-            ${local.net_dev.netdev}.irq = ${rtx_pci_dev.irq};
-            ${local.net_dev.netdev}.netdev_ops = &rtx_ether_ops;
+            SET_NETDEV_DEV(${local.rtx_net_dev.k_net_dev}, ${rtx_pci_dev.device});
+            strlcpy(${local.rtx_net_dev.k_net_dev}->name,
+                    ${config.ifname},
+                    sizeof(${local.rtx_net_dev.k_net_dev}->name));
+            ${local.rtx_net_dev.k_net_dev}->irq = ${rtx_pci_dev.irq};
+            ${local.rtx_net_dev.k_net_dev}->netdev_ops = &rtx_ether_ops;
 
-            error = register_netdev(&${local.net_dev.netdev});
+            error = register_netdev(${local.rtx_net_dev.k_net_dev});
             if (error)
             {
                 ${Log::info("cannot register the driver in the net subsystem")};
@@ -281,14 +316,11 @@
              * XXX: the cast is here because the compiler resolve the
              * type of rtx_pci_dev.pci_device to the type of
              * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
-             *
-             * Also, I'm getting placeholder in the generated code if
-             * I don't open a scope here.
              */
-            {
-                ${PCI::AbstractDevice} *rtx_pdev = ${rtx_pci_dev.pci_device};
-                ${cast local.rtx_pdev as PCI::AbstractDevice};
-                ${local.rtx_ether_ctx.init(local.net_dev, local.rtx_pdev)};
+            ${PCI::AbstractDevice} *workaround = ${rtx_pci_dev.pci_device};
+            ${cast local.workaround as PCI::AbstractDevice};
+            { /* XXX: I end up with a placeholder if I don't open a scope */
+                ${local.rtx_ether_ctx.init(local.rtx_net_dev, local.workaround)};
             }
 
             /* Register ourselves in the parent context: */
@@ -310,7 +342,7 @@
             ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
             memcpy(${local.rtx_ether_ctx.perm_addr},
                    ${local.rtx_ether_ctx.dev_addr},
-                   ${local.net_dev.netdev}.addr_len);
+                   ${local.rtx_net_dev.k_net_dev}->addr_len);
         }
 
         /* This chunk should be removed (see #26) */
@@ -327,15 +359,15 @@
          */
         chunk   PCI::pci_remove_hook(PCI::Device rtx_pci_dev)
         {
-            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.context};
-            ${Ethernet::AbstractDevice} *rtx_ether_dev = (${Ethernet::AbstractDevice}*) ${local.rtx_ether_ctx.net_device};
-
+            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
+            ${cast local.rtx_ether_ctx as Ethernet::Device}; /* XXX */
             BUG_ON(!rtx_ether_ctx);
 
-            ${cast local.rtx_ether_ctx as Ethernet::Device};
-            ${cast local.rtx_ether_dev as Ethernet::AbstractDevice};
-            unregister_netdev(&${local.rtx_ether_dev.netdev});
-            free_netdev(&${local.rtx_ether_dev.netdev});
+            ${Ethernet::AbstractDevice} *rtx_net_dev = ${local.rtx_ether_ctx.net_device};
+            ${cast local.rtx_net_dev as Ethernet::AbstractDevice}; /* XXX */
+
+            unregister_netdev(${local.rtx_net_dev.k_net_dev});
+            free_netdev(${local.rtx_net_dev.k_net_dev});
         }
 
         /* This chunk should be removed (see #26) */
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
@@ -16,8 +16,15 @@
     provided type   AbstractDevice
     {
         chunk       LKM::includes();
+        method      init(Builtin::symbol);
         decl        data_types();
-        attribute   Builtin::symbol netdev;
+
+        attribute   Builtin::symbol k_net_dev;
+        /*
+         * XXX: should be a Ethernet::Device, but that causes a circular
+         * dependency.
+         */
+        attribute   Builtin::symbol rtx_ether_ctx;
     }
 
     provided type   Device
@@ -34,9 +41,9 @@
          * I'd like to use better names here, but I'd like to understand the
          * difference between the two first:
          */
-        attribute   Builtin::symbol             perm_addr;
-        attribute   Builtin::symbol             dev_addr;
-        attribute   Builtin::symbol             irq;
+        attribute   Builtin::symbol perm_addr;
+        attribute   Builtin::symbol dev_addr;
+        attribute   Builtin::symbol irq;
     }
 
     required sequence   open(Ethernet::Device)
diff --git a/rathaxes/samples/e1000/pci.blt b/rathaxes/samples/e1000/pci.blt
--- a/rathaxes/samples/e1000/pci.blt
+++ b/rathaxes/samples/e1000/pci.blt
@@ -16,15 +16,15 @@
         {
         }
 
-        method  set_context(Builtin::symbol ctx)
+        method  set_rtx_context(Builtin::symbol ctx)
         {
-            pci_set_drvdata(&${self}->data, ${ctx});
+            pci_set_drvdata(${self.k_pci_dev}, ${ctx});
         }
 
         map
         {
-            data: ${self}->data;
-            drv_data: pci_get_drvdata(&${self}->data);
+            k_pci_dev: ((struct pci_dev *)${self});
+            rtx_pci_ctx: pci_get_drvdata((struct pci_dev *)${self});
         }
     }
 
@@ -52,13 +52,13 @@
                 int error;
                 ${PCI::AbstractDevice}  *enable_pdev = self->pdev;
                 ${cast local.enable_pdev as PCI::AbstractDevice};
-                error = pci_enable_device(&${local.enable_pdev.data});
+                error = pci_enable_device(${local.enable_pdev.k_pci_dev});
                 if (error)
                     return error;
-                error = pci_request_selected_regions(&${local.enable_pdev.data}, self->bars, ${config.name});
+                error = pci_request_selected_regions(${local.enable_pdev.k_pci_dev}, self->bars, ${config.name});
                 if (error)
                     return error;
-                pci_set_master(&${local.enable_pdev.data});
+                pci_set_master(${local.enable_pdev.k_pci_dev});
                 return 0;
             }
 
@@ -68,8 +68,8 @@
                 ${cast local.disable_pdev as PCI::AbstractDevice};
                 if (self->ioaddr)
                     iounmap(self->ioaddr);
-                pci_release_selected_regions(&${local.disable_pdev.data}, self->bars);
-                pci_disable_device(&${local.disable_pdev.data});
+                pci_release_selected_regions(${local.disable_pdev.k_pci_dev}, self->bars);
+                pci_disable_device(${local.disable_pdev.k_pci_dev});
             }
         }
 
@@ -78,7 +78,7 @@
             ${PCI::AbstractDevice} * workaround = (${PCI::AbstractDevice}*)pdev;
             ${cast local.workaround as PCI::AbstractDevice};
             ${self}->pdev = ${pdev};
-            ${self}->bars = pci_select_bars(&${local.workaround.data}, IORESOURCE_MEM);
+            ${self}->bars = pci_select_bars(${local.workaround.k_pci_dev}, IORESOURCE_MEM);
             ${self}->ioaddr = NULL;
             ${self}->context = NULL;
         }
@@ -97,20 +97,20 @@
         {
             ${PCI::AbstractDevice} *select_ioaddr_pdev = ${self}->pdev;
             ${cast local.select_ioaddr_pdev as PCI::AbstractDevice};
-            ${self}->ioaddr = pci_ioremap_bar(&${local.select_ioaddr_pdev.data}, ${bar});
+            ${self}->ioaddr = pci_ioremap_bar(${local.select_ioaddr_pdev.k_pci_dev}, ${bar});
         }
 
-        method  set_context(Builtin::symbol ctx)
+        method  set_rtx_drv_context(Builtin::symbol ctx)
         {
             ${self}->context = ctx;
         }
 
         map
         {
-            context: ${self}->context;
-            device: &${self}->pdev->data.dev;
+            rtx_drv_context: ${self}->context;
+            device: &((struct pci_dev *)(${self})->pdev)->dev;
             pci_device: ${self}->pdev;
-            irq: ${self}->pdev->data.irq;
+            irq: ((struct pci_dev *)(${self})->pdev)->irq;
             bars: ${self}->bars;
             ioaddr: ${self}->ioaddr;
             BAR_0: 0;
@@ -151,7 +151,7 @@
                     ${local.rtx_pci_dev.init(local.rtx_pdev)};
                 }
 
-                /* ${local.pdev.set_context(local.rtx_pci_dev)}; */
+                /* ${local.pdev.set_rtx_context(local.rtx_pci_dev)}; */
                 pci_set_drvdata(pdev, rtx_pci_dev);
 
                 /* ${local.rtx_pci_dev.enable()}; */
@@ -184,7 +184,7 @@
                 return 0;
 
             fail:
-                /* ${local.pdev.set_context(NULL)}; */
+                /* ${local.pdev.set_rtx_drv_context(NULL)}; */
                 pci_set_drvdata(pdev, NULL);
                 kfree(rtx_pci_dev);
                 return error;
@@ -210,7 +210,7 @@
             {
                 ${PCI::AbstractDevice}  *rtx_pdev = (${PCI::AbstractDevice}*)pdev;
                 ${cast local.rtx_pdev as PCI::AbstractDevice};
-                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.drv_data};
+                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.rtx_pci_ctx};
 
                 BUG_ON(!rtx_pci_dev);
 
diff --git a/rathaxes/samples/e1000/pci.rti b/rathaxes/samples/e1000/pci.rti
--- a/rathaxes/samples/e1000/pci.rti
+++ b/rathaxes/samples/e1000/pci.rti
@@ -10,10 +10,15 @@
 
         chunk       LKM::includes();
         method      init(PCI::AbstractDevice);
-        method      set_context(Builtin::symbol);
+        /*
+         * XXX: the argument should be a PCI::Device but that causes a circular
+         * dependency:
+         */
+        method      set_rtx_context(Builtin::symbol);
 
-        attribute   Builtin::symbol data;
-        attribute   Builtin::symbol drv_data;
+        attribute   Builtin::symbol k_pci_dev;
+        /* XXX: should be PCI::Device (see above point) */
+        attribute   Builtin::symbol rtx_pci_ctx;
     }
 
     provided type   PCI::Device
@@ -27,9 +32,9 @@
         method      enable();
         method      disable();
         method      select_ioaddr(Builtin::number);
-        method      set_context(Builtin::symbol);
+        method      set_rtx_drv_context(Builtin::symbol);
 
-        attribute   Builtin::symbol         context;
+        attribute   Builtin::symbol         rtx_drv_context;
         attribute   Device::AbstractDevice  device;
         attribute   PCI::AbstractDevice     pci_device;
         attribute   Builtin::symbol         ioaddr;
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
@@ -14,7 +14,7 @@
 
         map
         {
-            data: ${self}->data;
+            k_sk_buff: ((struct sk_buff *)${self});
         }
     }
 
@@ -46,11 +46,12 @@
                  */
                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
                 ${cast local.skb as Socket::AbstractSKBuff};
-                ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.data}.protocol) };
+                ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.k_sk_buff}->protocol) };
+
                 static const char * const ip_summed_values[] = {
                     "none", "unnecessary", "complete", "partial"
                 };
-                struct skb_shared_info *shinfo = skb_shinfo(&${local.skb.data});
+                struct skb_shared_info *shinfo = skb_shinfo(${local.skb.k_sk_buff});
 
                 pr_info(
                         "\t protocol = %#-5x (%s) ip_summed = %d (%s)\n"
@@ -59,8 +60,8 @@
                         "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u",
                         /* XXX: can't use ${local.ethernet_proto.id} here (issue #52): */
                         ethernet_proto.id, ${local.ethernet_proto.str},
-                        ${local.skb.data}.ip_summed, ip_summed_values[${local.skb.data}.ip_summed],
-                        ${local.skb.data}.len, ${local.skb.data}.data_len, skb_headlen(&${local.skb.data}),
+                        ${local.skb.k_sk_buff}->ip_summed, ip_summed_values[${local.skb.k_sk_buff}->ip_summed],
+                        ${local.skb.k_sk_buff}->len, ${local.skb.k_sk_buff}->data_len, skb_headlen(${local.skb.k_sk_buff}),
                         shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type
                 );
             }
@@ -72,14 +73,13 @@
                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
                 ${cast local.skb as Socket::AbstractSKBuff};
 
-                WARN_ON(!skb);
-                WARN_ON(!${local.skb.data}.data);
+                WARN_ON(!${local.skb.k_sk_buff});
                 WARN_ON(self->dma_handle);
 
                 self->dma_handle = dma_map_single(
                         dev,
-                        &${local.skb.data}.data,
-                        skb_headlen(&${local.skb.data}),
+                        ${local.skb.k_sk_buff},
+                        skb_headlen(${local.skb.k_sk_buff}),
                         direction);
                 int err = dma_mapping_error(dev, self->dma_handle);
                 if (err)
@@ -97,18 +97,17 @@
                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
                 ${cast local.skb as Socket::AbstractSKBuff};
 
-                WARN_ON(!${local.skb});
-                WARN_ON(!${local.skb.data}.data);
+                WARN_ON(!${local.skb.k_sk_buff});
 
                 if (self->dma_handle)
                 {
                     dma_unmap_single(dev,
                             self->dma_handle,
-                            skb_headlen(&${local.skb.data}),
+                            skb_headlen(${local.skb.k_sk_buff}),
                             direction);
                     self->dma_handle = 0;
                 }
-                dev_kfree_skb_any(&${local.skb.data});
+                dev_kfree_skb_any(${local.skb.k_sk_buff});
                 self->skbuff = 0;
             }
         }
@@ -131,22 +130,22 @@
 
         method   map_to(Device::AbstractDevice dev)
         {
-            rtx_socket_skbuff_map(${self}, &${dev.data}, DMA_TO_DEVICE);
+            rtx_socket_skbuff_map(${self}, ${dev.k_device}, DMA_TO_DEVICE);
         }
 
         method   map_from(Device::AbstractDevice dev)
         {
-            rtx_socket_skbuff_map(${self}, &${dev.data}, DMA_FROM_DEVICE);
+            rtx_socket_skbuff_map(${self}, ${dev.k_device}, DMA_FROM_DEVICE);
         }
 
         method   unmap_to_and_free(Device::AbstractDevice dev)
         {
-            rtx_socket_skbuff_unmap_and_free(${self}, &${dev.data}, DMA_TO_DEVICE);
+            rtx_socket_skbuff_unmap_and_free(${self}, ${dev.k_device}, DMA_TO_DEVICE);
         }
 
         method   unmap_from_and_free(Device::AbstractDevice dev)
         {
-            rtx_socket_skbuff_unmap_and_free(${self}, &${dev.data}, DMA_FROM_DEVICE);
+            rtx_socket_skbuff_unmap_and_free(${self}, ${dev.k_device}, DMA_FROM_DEVICE);
         }
 
         map
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
@@ -5,7 +5,8 @@
     {
         chunk       LKM::includes();
         decl        data_types();
-        attribute   Builtin::symbol data;
+
+        attribute   Builtin::symbol k_sk_buff;
     }
 
     provided type   SKBuff