diff options
author | Mykyta Iziumtsev <mykyta.iziumtsev@linaro.org> | 2017-10-18 09:08:13 +0200 |
---|---|---|
committer | Mykyta Iziumtsev <mykyta.iziumtsev@linaro.org> | 2017-10-18 12:00:21 +0200 |
commit | 68c793425069c36fb9489ef3ac73fb2c6344fae9 (patch) | |
tree | 4ae036139710fdcce31b3f3fb1bcfc390009877b | |
parent | bc813281006f4267c1dc1797ac0aad05e1a53a9c (diff) |
Attempt to fix e1000e TX pathe1000e_tx
-rw-r--r-- | drivers/e1000e.c | 59 | ||||
-rw-r--r-- | drivers/r8169.c | 24 | ||||
-rw-r--r-- | include/common.h | 12 | ||||
-rw-r--r-- | include/drivers/driver_ops.h | 7 | ||||
-rw-r--r-- | kernel/4.13.0/e1000e/netdev.c | 4 | ||||
-rw-r--r-- | src/userspace_io.c | 9 |
6 files changed, 65 insertions, 50 deletions
diff --git a/drivers/e1000e.c b/drivers/e1000e.c index cf022e7..43fbd66 100644 --- a/drivers/e1000e.c +++ b/drivers/e1000e.c @@ -2,11 +2,13 @@ #include <endian.h> #include <unistd.h> #include <stdint.h> +#include <string.h> #include <linux/types.h> #include <drivers/driver_ops.h> #include <mm_api.h> #include <vfio_api.h> +#include <reg_api.h> extern void *bar0; @@ -23,6 +25,9 @@ typedef uint64_t odpdrv_u64le_t; typedef uint64_t odpdrv_u64be_t; #define odpdrv_cpu_to_le_64(value) (value) +#define odpdrv_cpu_to_le_32(value) (value) +#define odpdrv_cpu_to_le_16(value) (value) +#define odpdrv_le_to_cpu_64(value) (value) #define odpdrv_le_to_cpu_32(value) (value) #define odpdrv_le_to_cpu_16(value) (value) @@ -46,6 +51,11 @@ typedef uint64_t odpdrv_u64be_t; typedef struct e1000e_tx_desc { odpdrv_u64le_t buffer_addr; /* Address of the descriptor's data buffer */ union { +#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ +#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ +#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ +#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ + odpdrv_u32le_t data; struct { odpdrv_u16le_t length; /* Data buffer length */ @@ -120,12 +130,10 @@ static void print_packet(unsigned char *buffer) static void e1000e_rx_desc_push(e1000e_rx_desc_t *rx_ring, int idx, dma_addr_t dma_addr, volatile void *ioaddr) { - printf("Writing RX desc #%i (%p), buf at %p\n", idx, rx_ring + idx, (void *)dma_addr); rx_ring[idx].read.buffer_addr = odpdrv_cpu_to_le_64(dma_addr); dma_wmb(); - // FIXME: proper le register write - *(uint32_t *)(ioaddr + E1000_RDT_OFFSET) = idx; + io_write32(odpdrv_cpu_to_le_32(idx), ioaddr + E1000_RDT_OFFSET); } static int e1000e_rx_fill(int device, void *rxring, struct iomem data, @@ -186,11 +194,44 @@ void *e1000e_map_mmio(int device) return vfio_mmap_region(device, 0); } -static int e1000e_tx_fill(int device, void *tx_data, struct iomem data, - char *tx_buff[]) +void e1000e_xmit(void *txring, struct iomem data, volatile void *ioaddr) { - /* Nothing to do here */ - return 0; + /* test udp packet */ + static const char pkt_udp[] = { + 0x02, 0x50, 0x43, 0xff, 0xff, 0x01, /* mac dst */ + 0x00, 0x60, 0xdd, 0x45, 0xe5, 0x67, /* mac src */ + 0x08, 0x00, 0x45, 0x00, 0x00, 0x32, + 0x38, 0xb8, 0x40, 0x00, 0x40, 0x11, + 0x1e, 0xae, 0xc0, 0xa8, 0x31, 0x03, /* ip src: 192.168.49.3 and dst 192.168.49.1 */ + 0xc0, 0xa8, 0x31, 0x01, 0xed, 0x19, + 0x00, 0x35, 0x00, 0x1e, 0x8b, 0xf4, + 0xc4, 0x2e, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, + 0x00, 0x01, 0x00, 0x01 + }; + const int idx = 0; + e1000_tx_desc_t *tx_desc = (e1000_tx_desc_t *)txring + idx; + char *tx_buff = (char *)(data.vaddr + idx * 2048); + uint32_t txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS | + E1000_TXD_CMD_IDE; + + /* XXX FIXME need proper packet size and sizeof(src) *NOT* dst */ + memcpy(tx_buff, pkt_udp, sizeof(pkt_udp)); + tx_desc->buffer_addr = odpdrv_cpu_to_le_64(data.iova + idx * 2048); + tx_desc->lower.data = odpdrv_cpu_to_le_32(txd_cmd | sizeof(pkt_udp)); + tx_desc->upper.data = odpdrv_cpu_to_le_32(0); + + dma_wmb(); + + printf("Triggering xmit of dummy packet\n"); + printf("tx_desc->buffer_addr == 0x%016lx\n", tx_desc->buffer_addr); + printf("tx_desc->lower == 0x%08x\n", tx_desc->lower.data); + printf("tx_desc->upper == 0x%08x\n", tx_desc->upper.data); + + io_write32(odpdrv_cpu_to_le_32(idx + 1), ioaddr + E1000_TDT_OFFSET); + + return; } const struct driver_ops e1000e_ops = { @@ -198,8 +239,8 @@ const struct driver_ops e1000e_ops = { .device = 0xdead, .vfio_quirks = NULL, .rx_fill = e1000e_rx_fill, - .tx_fill = e1000e_tx_fill, .recv = e1000e_recv, - .xmit = NULL, + .xmit = e1000e_xmit, .map_mmio = e1000e_map_mmio, }; + diff --git a/drivers/r8169.c b/drivers/r8169.c index 922a6a0..e90ed7b 100644 --- a/drivers/r8169.c +++ b/drivers/r8169.c @@ -132,30 +132,19 @@ static inline void rtl8169_map_to_asic_tx(struct TxDesc *desc, dma_addr_t mappin desc->addr = cpu_to_le64(mapping); } -static int r8169_tx_fill(int device, void *tx_data, struct iomem data, - char *tx_buff[]) -{ - int i; - struct TxDesc *r8169_txring = (struct TxDesc *) tx_data; - - for (i = 0; i < NUM_TX_DESC; i++) { - rtl8169_map_to_asic_tx(&r8169_txring[i], data.iova + i * 2048, - 2048); - tx_buff[i] = (char *)(data.vaddr + i * 2048); - } - - return 0; -} - -void r8169_xmit(void *txring, char *tx_buff[], volatile void *ioaddr) +void r8169_xmit(void *txring, struct iomem data, volatile void *ioaddr) { + const int idx = 0; __u32 opts[2]; __u32 status, len; int entry = 0; struct TxDesc *r8169_txring = (struct TxDesc *)txring; + char *tx_buff = (char *)(data.vaddr + idx * 2048); /* XXX FIXME need proper packet size and sizeof(src) *NOT* dst */ - memcpy(tx_buff[0], pkt_udp, sizeof(pkt_udp)); + memcpy(tx_buff, pkt_udp, sizeof(pkt_udp)); + rtl8169_map_to_asic_tx(&r8169_txring[idx], data.iova + idx * 2048, + 2048); /* FIXME no fragmentation support */ opts[0] = DescOwn; opts[0] |= FirstFrag | LastFrag; @@ -188,7 +177,6 @@ const struct driver_ops r8169_ops = { .device = 0x8168, .vfio_quirks = NULL, .rx_fill = r8169_rx_fill, - .tx_fill= r8169_tx_fill, .recv = r8169_recv, .xmit = r8169_xmit, .map_mmio = r8169_map_mmio, diff --git a/include/common.h b/include/common.h index a59508e..38570d7 100644 --- a/include/common.h +++ b/include/common.h @@ -20,14 +20,6 @@ static inline int uio_rx_fill(const struct driver_ops *e, int device, return 0; } -static inline int uio_tx_fill(const struct driver_ops *e, int device, - void *txring, struct iomem data, char *tx_buf[]) -{ - if (e && e->tx_fill) - return e->tx_fill(device, txring, data, tx_buf); - - return 0; -} static inline void uio_recv(const struct driver_ops *e, void *rxring, char *rxbuffers[], volatile void *iomem) @@ -39,10 +31,10 @@ static inline void uio_recv(const struct driver_ops *e, void *rxring, } static inline void uio_xmit(const struct driver_ops *e, void *txring, - char *txbuffers[], volatile void *iomem) + struct iomem tx_data, volatile void *iomem) { if (e && e->xmit) - e->xmit(txring, txbuffers, iomem); + e->xmit(txring, tx_data, iomem); return; } diff --git a/include/drivers/driver_ops.h b/include/drivers/driver_ops.h index 016d646..4ab973d 100644 --- a/include/drivers/driver_ops.h +++ b/include/drivers/driver_ops.h @@ -7,16 +7,13 @@ struct driver_ops { __u16 device; /* VFIO/PCI quirks */ int (*vfio_quirks)(void); - /* prepare Tx descriptors */ + /* prepare Rx descriptors */ int (*rx_fill)(int device, void *rxring, struct iomem data, char *rx_buf[], volatile void *iomem); - /* prepare Tx descriptors */ - int (*tx_fill)(int device, void *txring, struct iomem data, - char *rx_buf[]); /* receive */ void (*recv)(void *rxring, char *rxbuffers[], volatile void *iomem); /* xmit */ - void (*xmit)(void *txring, char *txbuffers[], volatile void *iomem); + void (*xmit)(void *txring, struct iomem data, volatile void *iomem); /* map MMIO */ void *(*map_mmio)(int device); }; diff --git a/kernel/4.13.0/e1000e/netdev.c b/kernel/4.13.0/e1000e/netdev.c index 5892d07..14dd72b 100644 --- a/kernel/4.13.0/e1000e/netdev.c +++ b/kernel/4.13.0/e1000e/netdev.c @@ -5688,6 +5688,10 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) */ wmb(); + printk("tx_desc->buffer_addr == 0x%016llx\n", tx_desc->buffer_addr); + printk("tx_desc->lower == 0x%08x\n", tx_desc->lower.data); + printk("tx_desc->upper == 0x%08x\n", tx_desc->upper.data); + tx_ring->next_to_use = i; } diff --git a/src/userspace_io.c b/src/userspace_io.c index 3eae859..b7afb7e 100644 --- a/src/userspace_io.c +++ b/src/userspace_io.c @@ -80,7 +80,6 @@ int main(int argc, char *argv[]) char group_uuid[64]; /* 37 should be enough */ char drv_name[64]; char *rx_buff[256]; - char *tx_buff[256]; __u32 opts = 0; memset(group_uuid, 0, sizeof(group_uuid)); @@ -164,14 +163,8 @@ int main(int argc, char *argv[]) goto out; } - /* Nothing to do actually */ - if (uio_tx_fill(exec_ops, device, txring, tx_data, tx_buff) != 0) { - printf("Could not fill TxRing\n"); - goto out; - } - ioctl(device, 500, NULL); - uio_xmit(exec_ops, txring, tx_buff, mmio); + uio_xmit(exec_ops, txring, tx_data, mmio); uio_recv(exec_ops, rxring, rx_buff, mmio); out: |