# HG changeset patch # User Louis Opter # Date 1341734425 -7200 # Node ID 27f0e70df3428a565b2b34667f2b134600e34c36 # Parent 71f76c0f235ffc0f8743ada95e73d57a13a1d982 Wip on the transmission, tx init done, and tx hooked from Ethernet send diff -r 71f76c0f235f -r 27f0e70df342 e1000_fix_rdt_set.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/e1000_fix_rdt_set.patch Sun Jul 08 10:00:25 2012 +0200 @@ -0,0 +1,42 @@ +# 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 71f76c0f235f -r 27f0e70df342 e1000_implement_the_frame_transmission_chunk.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/e1000_implement_the_frame_transmission_chunk.patch Sun Jul 08 10:00:25 2012 +0200 @@ -0,0 +1,74 @@ +# HG changeset patch +# Parent 1a5a83776de5ecff15e42930c7741f5b4f2ada13 +rathaxes: start to queue up packets in the TX ring on the e1000 sample + +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 @@ + } + } + } ++ ++ template sequence e1000::xmit(Ethernet::Device ctx, Socket::SKBuff skb) ++ { ++ chunk ::CALL() ++ { ++ /* ++ * Put packets on the TX ring, must return NETDEV_TX_OK or ++ * NETDEV_TX_BUSY. ++ */ ++ (void)1; // See #10 ++ { ++ ${Log::info("xmit: skbuff details:")}; ++ } ++ 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 @@ + provided chunk ::CALL(); + } + ++ provided sequence e1000::xmit(Ethernet::Device, Socket::SKBuff) ++ { ++ provided chunk ::CALL(); ++ } ++ + provided sequence e1000::register_read32(e1000::Context, e1000::Register) + { + provided chunk LKM::prototypes(); +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 +@@ -46,6 +46,7 @@ + Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) + { + Log::info("we have one packet to transmit!"); ++ e1000::xmit(dev, skb); + } + + LKM::init() diff -r 71f76c0f235f -r 27f0e70df342 e1000_initialize_transmission.patch --- a/e1000_initialize_transmission.patch Mon May 21 04:09:23 2012 +0200 +++ b/e1000_initialize_transmission.patch Sun Jul 08 10:00:25 2012 +0200 @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 1328cb41b1bb4d39588c1934c841b3e4362f7413 +# Parent e2e48ad161482555c5e87550e76cf15ef7fdbd3e rathaxes: initialize transmission on the e1000 sample: - This is documented in details in the sections 14.5 and 3.3 of the @@ -8,32 +8,111 @@ 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,24 @@ - } +@@ -34,6 +34,59 @@ } -+ template type e1000:TxDescriptor() + /* ++ * 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() ++ chunk LKM::includes() + { -+ typedef int ${e1000:TxDescriptor}; -+ -+ static const ${e1000:TxDescriptor} force_rtx_e1000_tx_descriptor_decl; ++ 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. * -@@ -103,6 +121,7 @@ + * - 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; @@ -41,7 +120,36 @@ } *rtx_e1000_ctx_p; } -@@ -736,6 +755,20 @@ +@@ -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 @@ } /* @@ -56,9 +164,93 @@ + * 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 71f76c0f235f -r 27f0e70df342 series --- a/series Mon May 21 04:09:23 2012 +0200 +++ b/series Sun Jul 08 10:00:25 2012 +0200 @@ -1,1 +1,3 @@ +e1000_fix_rdt_set.patch e1000_initialize_transmission.patch +e1000_implement_the_frame_transmission_chunk.patch