# HG changeset patch # User Louis Opter # Date 1334446799 -7200 # Node ID f07f6c6d6cd47598ee413fc6ab674067571339ec # Parent 501bf9cf65dc8819db34d651d6f266aa91947106 WIP on RX on e1000 diff -r 501bf9cf65dc -r f07f6c6d6cd4 e1000_initialize_reception.patch --- 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 ++ ++ 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 ++ ++ static const ${Socket::SKBuff} force_rtx_lnux_skbuf_decl; + } + + chunk ::decl()