aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMykyta Iziumtsev <mykyta.iziumtsev@linaro.org>2017-10-19 16:35:31 +0200
committerMykyta Iziumtsev <mykyta.iziumtsev@linaro.org>2017-10-19 16:37:00 +0200
commit4887258ef5425fb3e3c4dd99ea9f7c1d01990c6e (patch)
tree075a1844689c3125014bef43dd6cd400fb55752c
parentb1a13abb1fa6caeed3098d17dbd281d29db7d170 (diff)
Work in progress: 2017-10-192017-10-19
-rw-r--r--drivers/e1000e.c63
-rw-r--r--drivers/r8169.c4
-rw-r--r--include/common.h4
-rw-r--r--include/drivers/driver_ops.h4
-rw-r--r--kernel/4.13.0/e1000e/e1000.h2
-rw-r--r--kernel/4.13.0/e1000e/netdev.c23
-rw-r--r--kernel/4.13.0/e1000e/vfio-net.c30
-rwxr-xr-xrun_e1000e.sh2
-rw-r--r--src/userspace_io.c5
9 files changed, 91 insertions, 46 deletions
diff --git a/drivers/e1000e.c b/drivers/e1000e.c
index f3e4cf6..1b30a32 100644
--- a/drivers/e1000e.c
+++ b/drivers/e1000e.c
@@ -128,40 +128,46 @@ static void print_packet(unsigned char *buffer)
}
#endif
-static void e1000e_rx_desc_push(e1000e_rx_desc_t *rx_ring, int idx, dma_addr_t dma_addr, volatile void *ioaddr)
-{
- rx_ring[idx].read.buffer_addr = odpdrv_cpu_to_le_64(dma_addr);
- dma_wmb();
-
- io_write32(odpdrv_cpu_to_le_32(idx), ioaddr + E1000_RDT_OFFSET);
-}
-
static int e1000e_rx_fill(int device, void *rxring, struct iomem data,
- char *rx_buff[], volatile void *ioaddr)
+ volatile char *rx_buff[], volatile void *ioaddr)
{
- e1000e_rx_desc_t *rx_ring = (e1000e_rx_desc_t *)rxring;
+ volatile e1000e_rx_desc_t *rx_ring = (e1000e_rx_desc_t *) rxring;
int i;
+ memset((void *)rx_ring, 0, E1000E_RX_RING_SIZE_DEFAULT * sizeof(e1000e_rx_desc_t));
+
/* TODO: support variable rx_ring size, configuration via ethtool */
- for (i = 0; i < E1000E_RX_RING_SIZE_DEFAULT; i++) {
- rx_buff[i] = (char *)(data.vaddr + i * E1000E_RX_BUF_SIZE);
- e1000e_rx_desc_push(rx_ring, i, data.iova + i * E1000E_RX_BUF_SIZE, ioaddr);
+ for (i = 0; i < E1000E_RX_RING_SIZE_DEFAULT - 1; i++) {
+ rx_buff[i] =
+ (char *) (data.vaddr + i * E1000E_RX_BUF_SIZE);
+ memset((void *) rx_buff[i], 0xa5, E1000E_RX_BUF_SIZE);
+ rx_ring[i].read.buffer_addr =
+ odpdrv_cpu_to_le_64(data.iova +
+ i * E1000E_RX_BUF_SIZE);
+ if (!(i & 15)) {
+ dma_wmb();
+ io_write32(odpdrv_cpu_to_le_32(i),
+ ioaddr + E1000_RDT_OFFSET);
+ }
}
return 0;
}
-static void e1000e_recv(void *rxring, char *rx_buff[], volatile void *ioaddr)
+static void e1000e_recv(void *rxring, volatile char *rx_buff[], volatile void *ioaddr)
{
- e1000e_rx_desc_t *rx_ring = (e1000e_rx_desc_t *)rxring;
+ volatile e1000e_rx_desc_t *rx_ring = (e1000e_rx_desc_t *)rxring;
int i = 0;
while (1) {
if (i >= E1000E_RX_RING_SIZE_DEFAULT)
i = 0;
for (; i < E1000E_RX_RING_SIZE_DEFAULT; i++) {
- e1000e_rx_desc_t *rx_desc = rx_ring + i;
- uint32_t status = odpdrv_le_to_cpu_32(rx_desc->wb.upper.status_error);
+ volatile e1000e_rx_desc_t *rx_desc = rx_ring + i;
+ uint32_t status;
+
+ dma_rmb();
+ status = odpdrv_le_to_cpu_32(rx_desc->wb.upper.status_error);
if (!(status & E1000E_RX_DESC_STAT_DONE)) {
usleep(100*1000);
@@ -179,6 +185,13 @@ static void e1000e_recv(void *rxring, char *rx_buff[], volatile void *ioaddr)
} else {
int pkt_size = odpdrv_le_to_cpu_16(rx_desc->wb.upper.length);
+#if 0
+ while ((unsigned char)rx_buff[i][0] == 0xa5U) {
+ printf("Packet payload is garbage, waiting ...\n");
+ usleep(1000);
+ printf("Done waiting\n");
+ }
+#endif
printf("desc[%03d]: size= %5d ", i, pkt_size);
print_packet((unsigned char *)rx_buff[i]);
printf("\n");
@@ -197,9 +210,9 @@ void *e1000e_map_mmio(int device)
void e1000e_xmit(void *txring, struct iomem data, volatile void *ioaddr)
{
/* test udp packet */
- static const char pkt_udp[] = {
+ static const unsigned char pkt_udp[] = {
0x02, 0x50, 0x43, 0xff, 0xff, 0x01, /* mac dst */
- 0x00, 0x60, 0xdd, 0x45, 0xe5, 0x67, /* mac src */
+ 0xf4, 0x4d, 0x30, 0x64, 0x43, 0xf7, /* 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 */
@@ -216,12 +229,12 @@ void e1000e_xmit(void *txring, struct iomem data, volatile void *ioaddr)
E1000_TXD_CMD_IDE;
for (idx = 0; idx < 100; idx++) {
- e1000_tx_desc_t *tx_desc =
+ volatile e1000_tx_desc_t *tx_desc =
(e1000_tx_desc_t *) txring + idx;
- char *tx_buff = (char *) (data.vaddr + idx * 2048);
+ volatile unsigned char *tx_buff = (unsigned char *) (data.vaddr + idx * 2048);
/* XXX FIXME need proper packet size and sizeof(src) *NOT* dst */
- memcpy(tx_buff, pkt_udp, sizeof(pkt_udp));
+ memcpy((void *)tx_buff, pkt_udp, sizeof(pkt_udp));
tx_desc->buffer_addr =
odpdrv_cpu_to_le_64(data.iova + idx * 2048);
tx_desc->lower.data =
@@ -231,6 +244,8 @@ void e1000e_xmit(void *txring, struct iomem data, volatile void *ioaddr)
dma_wmb();
printf("Triggering xmit of dummy packet\n");
+ print_packet((void *)tx_buff);
+
printf("tx_desc->buffer_addr == 0x%016lx\n",
tx_desc->buffer_addr);
printf("tx_desc->lower == 0x%08x\n", tx_desc->lower.data);
@@ -247,6 +262,10 @@ void e1000e_xmit(void *txring, struct iomem data, volatile void *ioaddr)
printf("TDT == 0x%08x\n", io_read32(ioaddr + E1000_TDT_OFFSET));
printf("TDH == 0x%08x\n", io_read32(ioaddr + E1000_TDH_OFFSET));
+ 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);
}
return;
diff --git a/drivers/r8169.c b/drivers/r8169.c
index e90ed7b..dd34b82 100644
--- a/drivers/r8169.c
+++ b/drivers/r8169.c
@@ -63,7 +63,7 @@ static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
}
static int r8169_rx_fill(int device, void *rx_data, struct iomem data,
- char *rx_buff[], volatile void *ioaddr)
+ volatile char *rx_buff[], volatile void *ioaddr)
{
int i;
struct RxDesc *r8169_rxring = (struct RxDesc *) rx_data;
@@ -77,7 +77,7 @@ static int r8169_rx_fill(int device, void *rx_data, struct iomem data,
return 0;
}
-void r8169_recv(void *rxring, char *rx_buff[], volatile void *ioaddr)
+void r8169_recv(void *rxring, volatile char *rx_buff[], volatile void *ioaddr)
{
int i = 0;
struct RxDesc *r8169_rxring = (struct RxDesc *)rxring;
diff --git a/include/common.h b/include/common.h
index 38570d7..a3adc66 100644
--- a/include/common.h
+++ b/include/common.h
@@ -12,7 +12,7 @@ static inline int uio_quirks(const struct driver_ops *e)
}
static inline int uio_rx_fill(const struct driver_ops *e, int device,
- void *rxring, struct iomem data, char *rx_buf[],
+ void *rxring, struct iomem data, volatile char *rx_buf[],
volatile void *ioaddr)
{
if (e && e->rx_fill)
@@ -22,7 +22,7 @@ static inline int uio_rx_fill(const struct driver_ops *e, int device,
}
static inline void uio_recv(const struct driver_ops *e, void *rxring,
- char *rxbuffers[], volatile void *iomem)
+ volatile char *rxbuffers[], volatile void *iomem)
{
if (e && e->recv)
e->recv(rxring, rxbuffers, iomem);
diff --git a/include/drivers/driver_ops.h b/include/drivers/driver_ops.h
index 4ab973d..9da5312 100644
--- a/include/drivers/driver_ops.h
+++ b/include/drivers/driver_ops.h
@@ -9,9 +9,9 @@ struct driver_ops {
int (*vfio_quirks)(void);
/* prepare Rx descriptors */
int (*rx_fill)(int device, void *rxring, struct iomem data,
- char *rx_buf[], volatile void *iomem);
+ volatile char *rx_buf[], volatile void *iomem);
/* receive */
- void (*recv)(void *rxring, char *rxbuffers[], volatile void *iomem);
+ void (*recv)(void *rxring, volatile char *rxbuffers[], volatile void *iomem);
/* xmit */
void (*xmit)(void *txring, struct iomem data, volatile void *iomem);
/* map MMIO */
diff --git a/kernel/4.13.0/e1000e/e1000.h b/kernel/4.13.0/e1000e/e1000.h
index 06ad27f..1955604 100644
--- a/kernel/4.13.0/e1000e/e1000.h
+++ b/kernel/4.13.0/e1000e/e1000.h
@@ -319,6 +319,7 @@ struct e1000_adapter {
struct msix_entry *msix_entries;
int int_mode;
u32 eiac_mask;
+ u32 irq_mask;
u32 eeprom_wol;
u32 wol;
@@ -507,6 +508,7 @@ void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
void e1000e_get_hw_control(struct e1000_adapter *adapter);
void e1000e_release_hw_control(struct e1000_adapter *adapter);
void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr);
+void e1000e_trigger_lsc(struct e1000_adapter *adapter);
extern unsigned int copybreak;
diff --git a/kernel/4.13.0/e1000e/netdev.c b/kernel/4.13.0/e1000e/netdev.c
index 5892d07..fd28d38 100644
--- a/kernel/4.13.0/e1000e/netdev.c
+++ b/kernel/4.13.0/e1000e/netdev.c
@@ -2246,11 +2246,11 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
if (adapter->msix_entries) {
ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
- ew32(IMS, adapter->eiac_mask | E1000_IMS_LSC);
+ ew32(IMS, ~adapter->irq_mask & (adapter->eiac_mask | E1000_IMS_LSC));
} else if (hw->mac.type >= e1000_pch_lpt) {
- ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
+ ew32(IMS, ~adapter->irq_mask & (IMS_ENABLE_MASK | E1000_IMS_ECCER));
} else {
- ew32(IMS, IMS_ENABLE_MASK);
+ ew32(IMS, ~adapter->irq_mask & IMS_ENABLE_MASK);
}
e1e_flush();
}
@@ -4202,7 +4202,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
*
* Fire a link status change interrupt to start the watchdog.
**/
-static void e1000e_trigger_lsc(struct e1000_adapter *adapter)
+void e1000e_trigger_lsc(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
@@ -4219,13 +4219,12 @@ void e1000e_up(struct e1000_adapter *adapter)
clear_bit(__E1000_DOWN, &adapter->state);
- if (!test_bit(__E1000_VFIO_NET, &adapter->state)) {
- if (adapter->msix_entries)
- e1000_configure_msix(adapter);
- e1000_irq_enable(adapter);
+ if (adapter->msix_entries)
+ e1000_configure_msix(adapter);
+ e1000_irq_enable(adapter);
+ if (!test_bit(__E1000_VFIO_NET, &adapter->state)) {
netif_start_queue(adapter->netdev);
-
e1000e_trigger_lsc(adapter);
}
}
@@ -5926,8 +5925,10 @@ static void e1000_tx_timeout(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
- adapter->tx_timeout_count++;
- schedule_work(&adapter->reset_task);
+ if (!test_bit(__E1000_VFIO_NET, &adapter->state)) {
+ adapter->tx_timeout_count++;
+ schedule_work(&adapter->reset_task);
+ }
}
static void e1000_reset_task(struct work_struct *work)
diff --git a/kernel/4.13.0/e1000e/vfio-net.c b/kernel/4.13.0/e1000e/vfio-net.c
index 6a16f25..dd829af 100644
--- a/kernel/4.13.0/e1000e/vfio-net.c
+++ b/kernel/4.13.0/e1000e/vfio-net.c
@@ -87,6 +87,12 @@ static int e1000e_vfio_net_open(struct mdev_device *mdev)
dev_hold(adapter->netdev);
set_bit(__E1000_VFIO_NET, &adapter->state);
+ adapter->irq_mask =
+ E1000_IMS_RXT0 |
+ E1000_IMS_TXDW |
+ E1000_IMS_RXDMT0 |
+ E1000_IMS_RXSEQ;
+
if (netif_running(adapter->netdev))
e1000e_reinit_locked(adapter);
else
@@ -108,6 +114,8 @@ static void e1000e_vfio_net_release(struct mdev_device *mdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
clear_bit(__E1000_VFIO_NET, &adapter->state);
+ adapter->irq_mask = 0;
+
if (netif_running(adapter->netdev))
e1000e_reinit_locked(adapter);
else
@@ -319,6 +327,7 @@ static long e1000e_vfio_net_ioctl(struct mdev_device *mdev, unsigned int cmd,
/* return ret? */
return -ENOMEM;
+#if 0
printk(KERN_INFO"VFIO_IOMMU_MAP_DMA: about to dma_map_single(%p, %p, %lld, DMA_FROM_DEVICE)\n",
parent_dev, data, map.size);
mapping = dma_map_single(parent_dev, data, map.size,
@@ -329,11 +338,18 @@ static long e1000e_vfio_net_ioctl(struct mdev_device *mdev, unsigned int cmd,
kfree(data);
goto out;
}
+#else
+ data = dma_alloc_coherent(parent_dev, map.size, &mapping, GFP_KERNEL);
+ if (!data) {
+ if (net_ratelimit())
+ printk(KERN_ERR"Failed to dma_alloc_coherent buffer for userland!\n");
+ goto out;
+ }
+
+#endif
map.iova = mapping;
- ret = io_remap_pfn_range(vma, map.vaddr,
- virt_to_phys(data) >> PAGE_SHIFT,
- map.size, vma->vm_page_prot);
- printk(KERN_INFO"VFIO_IOMMU_MAP_DMA: io_remap_pfn_range %llx -> physmem <- @%llx, %lld:%d\n",
+ ret = dma_mmap_coherent(parent_dev, vma, data, mapping, map.size);
+ printk(KERN_INFO"VFIO_IOMMU_MAP_DMA: dma_map_coherent %llx -> physmem <- @%llx, %lld:%d\n",
map.vaddr, map.iova, map.size, ret);
if (ret != 0) {
dma_unmap_single(parent_dev, mapping, map.size,
@@ -347,7 +363,7 @@ static long e1000e_vfio_net_ioctl(struct mdev_device *mdev, unsigned int cmd,
netmdev->mappings_count);
netmdev->mappings[netmdev->mappings_count].dev = parent_dev;
netmdev->mappings[netmdev->mappings_count].vaddr = data;
- netmdev->mappings[netmdev->mappings_count].iova = mapping;
+ netmdev->mappings[netmdev->mappings_count].iova = map.iova;
netmdev->mappings[netmdev->mappings_count].size = map.size;
netmdev->mappings_count++;
@@ -370,6 +386,10 @@ out:
return 0;
+ case 500:
+ e1000e_trigger_lsc(adapter);
+ return 0;
+
default:
return -EOPNOTSUPP;
}
diff --git a/run_e1000e.sh b/run_e1000e.sh
index 4a74a20..844fb5a 100755
--- a/run_e1000e.sh
+++ b/run_e1000e.sh
@@ -7,4 +7,4 @@ insmod kernel/4.13.0/e1000e/e1000e.ko
sleep 1
ifconfig $intf up
./run.sh create $intf
-./uio -i 0 -d $(basename /sys/bus/mdev/devices/*) -n e1000e
+./uio -i 12 -d $(basename /sys/bus/mdev/devices/*) -n e1000e
diff --git a/src/userspace_io.c b/src/userspace_io.c
index 4677409..46fc21b 100644
--- a/src/userspace_io.c
+++ b/src/userspace_io.c
@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
int ret, c, group_id;
char group_uuid[64]; /* 37 should be enough */
char drv_name[64];
- char *rx_buff[256];
+ volatile char *rx_buff[256];
__u32 opts = 0;
memset(group_uuid, 0, sizeof(group_uuid));
@@ -164,6 +164,9 @@ int main(int argc, char *argv[])
}
ioctl(device, 500, NULL);
+
+ // usleep(30 * 1000 * 1000);
+
uio_xmit(exec_ops, txring, tx_data, mmio);
uio_recv(exec_ops, rxring, rx_buff, mmio);