# HG changeset patch # User Louis Opter # Date 1330882543 -3600 # Node ID 892b3bc7e43b1a84d113f344d828d5b6508c7a08 # Parent 51bea596df7f04226aeb0667488e2b49686ba2f0 Wip on the RX init in the e1000 sample diff -r 51bea596df7f -r 892b3bc7e43b e1000_initialize_reception.patch --- a/e1000_initialize_reception.patch Sun Mar 04 15:27:34 2012 +0100 +++ b/e1000_initialize_reception.patch Sun Mar 04 18:35:43 2012 +0100 @@ -17,18 +17,87 @@ 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 -@@ -36,6 +36,25 @@ +@@ -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,78 @@ } } -+ template type e1000::RingRx() ++ template type e1000::RxDescriptor() + { + chunk LKM::includes() + { ++ typedef int ${e1000::RxDescriptor}; ++ ++ #include + } + + chunk ::decl() + { ++ typedef struct rtx_e1000_rx_descriptor ++ { ++ /* actual types are in comments */ ++ unsigned long int /* __le64 */ buff_addr; ++ unsigned short /* __le16 */ length; ++ unsigned short /* __le16 */ csum; ++ unsigned char status; ++ unsigned char errors; ++ unsigned short /* __le16 */ special; ++ } *rtx_e1000_rx_descriptor_p; ++ } ++ ++ chunk ::init() ++ { ++ } ++ ++ map ++ { ++ } ++ } ++ ++ template type e1000::RxRing() ++ { ++ chunk LKM::includes() ++ { ++ typedef int ${e1000::RxRing}; ++ } ++ ++ 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; ++ rtx_e1000_rx_descriptor_p base; ++ void *dma_base; ++ ++ struct sk_buff *skbuffs[256 /* ${config.rx_ring_size} */]; ++ void *dma_skbuffs[256 /* ${config.rx_ring_size} */]; ++ }; + } + + chunk ::init() @@ -43,7 +112,7 @@ template type e1000::Register() { chunk LKM::includes() -@@ -64,6 +83,9 @@ +@@ -64,6 +139,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) */ @@ -53,7 +122,7 @@ }; } -@@ -132,7 +154,8 @@ +@@ -132,7 +210,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) */ @@ -63,14 +132,61 @@ }; } -@@ -491,9 +514,32 @@ - rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCAL, 0); - rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCT, 0); - rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCTTV, 0); +@@ -458,14 +537,23 @@ + chunk ::CALL + { + /* +- * This is documented in the Intel Gigabit Ethernet Controller +- * Software Developper manual. ++ * This part is documented in the Intel Gigabit Ethernet Controller ++ * Software Developper manual. (You can find it in the doc/hardware ++ * directory). + * + * Since this part is actually completely device specific it should + * not be written here. (but in the front-end). + */ + + /* ++ * shortcut hw_ctx... maybe we should directly take an ++ * e1000::Context? (but we would need to make it point back to ++ * the struct net_device) ++ */ ++ ${e1000::Context} hw_ctx; ++ hw_ctx = &${ctx}->hw_ctx; ++ ++ /* + * "General Configuration" (section 14.3): + * + * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & +@@ -478,22 +566,111 @@ + * - Finally, initialize all the statistic registers from + * E1000_CRCERRS to E1000_TSCTFC. + */ +- rtx_e1000_register_set32(&${ctx}->hw_ctx, E1000_CTRL, ++ ++ rtx_e1000_register_set32(hw_ctx, E1000_CTRL, + E1000_CMD_ASDE | + E1000_CMD_SLU); +- rtx_e1000_register_unset32(&${ctx}->hw_ctx, E1000_CTRL, ++ rtx_e1000_register_unset32(hw_ctx, E1000_CTRL, + E1000_CMD_LRST | + E1000_CMD_FRCSPD | + E1000_CMD_PHY_RST | + E1000_CMD_ILOS | + E1000_CMD_VME); +- rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCAH, 0); +- rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCAL, 0); +- rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCT, 0); +- rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCTTV, 0); - int i = 0; ++ rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0); ++ rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0); ++ rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0); ++ rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0); + int i = 0; /* CNorm workaround, the init part of for isn't generated */ for (i = 0; i != 64; ++i) - rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_CRCERRS + i * 4, 0); +- rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_CRCERRS + i * 4, 0); ++ rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + i * 4, 0); + + /* + * Receive initialization @@ -79,33 +195,156 @@ + * - Initialize the Multicast Table Array; + * - Program the interrupt mask register (done in + * e1000::activate_device_interruption); -+ * -+ * (We should use uint{32,16}_t but CNorm doesn't know them yet) ++ * - Allocate the receive descriptor ring and map it to make it ++ * accessible by the device. + */ -+ rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_RAL, ++ ++ /* (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)); + /* + * The 16 upper bits of RAH also store the AS bits (which should be + * 0) and the AV bit (should be 1 to set the address as valid). + */ -+ rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_RAH, ++ rtx_e1000_register_write32(hw_ctx, E1000_RAH, + *(unsigned short *)(&${ctx}->net_dev->dev_addr[4])); -+ rtx_e1000_register_set32(&${ctx}->hw_ctx, E1000_RAH, E1000_RAH_AV); ++ rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV); ++ + i = 0; /* CNorm workaround, the init part of for isn't generated */ + for (i = 0; i != 128; ++i) -+ rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_MTA + i * 4, 0); ++ rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0); ++ ++ 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) ++ { ++ ${Log::info("cannot allocate the descriptors for the Rx ring")}; ++ goto err_rx_ring_alloc; ++ } ++ ++ i = 0; ++ for (i = 0; i != ${config.rx_ring_size}; ++i) ++ { ++ hw_ctx->rx_ring.skbuffs[i] = netdev_allock_skb(${ctx}->net_device, ++ ${config.rx_buffer_len}); ++ if (!hw_ctx->rx_ring.skbuffs[i]) ++ { ++ ${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.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])) ++ { ++ ${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]); ++ } ++ ++ /* ++ * 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], ++ ${config.rx_buffer_len}, ++ DMA_FROM_DEVICE); ++ err_skbuffs_map: ++ dev_kfree_skb(hw_ctx->rx_ring.skbuffs[i]); ++ } ++ ++ dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->rx_ring.size, ++ hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base); ++ err_rx_ring_alloc: ++ return -ENOMEM; ++ } ++ } ++ ++ template sequence e1000::free_rx_tx(Ethernet::Device ctx) ++ { ++ chunk ::CALL ++ { ++ } } 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 -@@ -1,6 +1,8 @@ +@@ -1,6 +1,9 @@ interface e1000 : Socket, Ethernet, PCI, LKM { provided type e1000::Context; -+ provided type e1000::RingRx; ++ provided type e1000::RxDescriptor; ++ provided type e1000::RxRing; + /* * These two types should actually be registers definitions in the frontend: */ +@@ -57,6 +60,11 @@ + provided chunk ::CALL; + } + ++ provided sequence e1000::free_rx_tx(Ethernet::Device dev) ++ { ++ provided chunk ::CALL; ++ } ++ + provided sequence e1000::handle_interrupt(Ethernet::Device) + { + provided chunk ::CALL; +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 +@@ -102,7 +102,7 @@ + { + static int rtx_ethernet_close(struct net_device *dev) + { +- struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev); ++ struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev); + struct rtx_e1000_ctx* ctx = &rtx_ether_dev->hw_ctx; + + ${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 +@@ -24,7 +24,17 @@ + Ethernet::close(Ethernet::Device dev) + { + Log::info("closing the device"); ++ ++ /* ++ * Note: some calls to release resources must be done when IRQs are ++ * enabled (dma_free_coherent() for example). So we have to cleanup our ++ * stuff before free_interrupt_handler(). ++ */ ++ e1000::free_rx_tx(dev); ++ Log::info("free'ed up skbuffs"); ++ + e1000::free_interrupt_handler(dev); ++ Log::info("interrupt handler free'ed"); + } + + Ethernet::interrupt_handler(Ethernet::Device dev) +@@ -61,4 +71,11 @@ + PCI::set_master = true; + + Ethernet::ifname = "rtx%d"; ++ ++ e1000::rx_ring_size = 256; /* Number of incoming packets we can buffer */ ++ /* ++ * The e1000 supports seven receive buffer sizes: 256, 512, 1024, 2048, ++ * 4096, 8192 and 16384 bytes: ++ */ ++ e1000::rx_buffer_len = 2048; + }