# HG changeset patch # User Louis Opter # Date 1341809091 -7200 # Node ID 6432998a8245fb4dbdb7183ca5f369a45b899fb1 # Parent 27f0e70df3428a565b2b34667f2b134600e34c36 Finish the patches on the rx/tx init and wip on the actual tx diff -r 27f0e70df342 -r 6432998a8245 e1000_fix_rdt_set.patch --- 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); diff -r 27f0e70df342 -r 6432998a8245 e1000_implement_the_frame_transmission_chunk.patch --- 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(); + } + } diff -r 27f0e70df342 -r 6432998a8245 e1000_initialize_transmission.patch --- 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: diff -r 27f0e70df342 -r 6432998a8245 series --- 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