Bill Fischofer(Bill-Fischofer-Linaro) replied on github web page: platform/linux-generic/pktio/mdev/e1000e.c line 163 @@ -0,0 +1,605 @@ +/* Copyright (c) 2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "config.h" + +#ifdef ODP_MDEV + +#include <linux/types.h> +#include <protocols/eth.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> + +#include <odp_packet_io_internal.h> +#include <odp_posix_extensions.h> + +#include <odp/api/hints.h> +#include <odp/api/packet.h> +#include <odp/api/plat/packet_inlines.h> +#include <odp/drv/hints.h> +#include <odp/drv/mmio.h> + +#include <pktio/common.h> +#include <pktio/ethtool.h> +#include <pktio/mdev.h> +#include <pktio/sysfs.h> +#include <pktio/uapi_net_mdev.h> + +#define MODULE_NAME "e1000e" + +#define E1000E_TX_BUF_SIZE 2048U +#define E1000E_RX_BUF_SIZE 2048U + +/* RX queue definitions */ +#define E1000E_RX_QUEUE_NUM_MAX 1 + +#define E1000_RDH_OFFSET 0x02810UL +#define E1000_RDT_OFFSET 0x02818UL + +/** RX descriptor */ +typedef struct { + odp_u64le_t addr; +#define E1000E_RXD_STATUS_DONE 0x00000001UL +#define E1000E_RXD_STATUS_ERR_MASK 0xff000000UL + odp_u32le_t status; + odp_u16le_t length; + odp_u16le_t vlan; +} e1000e_rx_desc_t; + +/** RX queue data */ +typedef struct ODP_ALIGNED_CACHE { + e1000e_rx_desc_t *rx_descs; /**< RX queue base */ + odp_u32le_t *doorbell; /**< RX queue doorbell */ + + uint16_t rx_queue_len; /**< Number of RX desc entries */ + + uint16_t cidx; /**< Next RX desc to read */ + odp_u32le_t *pidx; /**< Next RX desc HW is going to write */ + + mdev_dma_area_t rx_data; /**< RX packet payload area */ + + odp_ticketlock_t lock; /**< RX queue lock */ +} e1000e_rx_queue_t; + +/* TX queue definitions */ +#define E1000E_TX_QUEUE_NUM_MAX 1 + +#define E1000_TDH_OFFSET 0x03810UL +#define E1000_TDT_OFFSET 0x03818UL + +typedef struct { + odp_u64le_t addr; /* Address of data buffer */ +#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ +#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ + odp_u32le_t cmd; + odp_u32le_t reserved; +} e1000e_tx_desc_t; + +/** TX queue data */ +typedef struct ODP_ALIGNED_CACHE { + e1000e_tx_desc_t *tx_descs; /**< TX queue base */ + odp_u32le_t *doorbell; /**< TX queue doorbell */ + + uint16_t tx_queue_len; /**< Number of TX desc entries */ + + uint16_t pidx; /**< Next TX desc to write */ + odp_u32le_t *cidx; /**< Next TX desc HW is going to read */ + + mdev_dma_area_t tx_data; /**< TX packet payload area */ + + odp_ticketlock_t lock; /**< TX queue lock */ +} e1000e_tx_queue_t; + +/** Packet socket using mediated e1000e device */ +typedef struct { + /** RX queue hot data */ + e1000e_rx_queue_t rx_queues[E1000E_RX_QUEUE_NUM_MAX]; + + /** TX queue hot data */ + e1000e_tx_queue_t tx_queues[E1000E_TX_QUEUE_NUM_MAX]; + + odp_pool_t pool; /**< pool to alloc packets from */ + + odp_bool_t lockless_rx; /**< no locking for RX */ + odp_bool_t lockless_tx; /**< no locking for TX */ + + odp_pktio_capability_t capa; /**< interface capabilities */ + + uint8_t *mmio; /**< MMIO region */ + + int sockfd; /**< control socket */ + + mdev_device_t mdev; /**< Common mdev data */ +} pktio_ops_e1000e_data_t; + +static void e1000e_rx_refill(e1000e_rx_queue_t *rxq, uint16_t from, + uint16_t num); +static void e1000e_wait_link_up(pktio_entry_t *pktio_entry); +static int e1000e_close(pktio_entry_t *pktio_entry); + +static int e1000e_mmio_register(pktio_ops_e1000e_data_t *pkt_e1000e, + uint64_t offset, uint64_t size) +{ + ODP_ASSERT(pkt_e1000e->mmio == NULL); + + pkt_e1000e->mmio = mdev_region_mmap(&pkt_e1000e->mdev, offset, size); + if (pkt_e1000e->mmio == MAP_FAILED) { + ODP_ERR("Cannot mmap MMIO\n"); + return -1; + } + + ODP_DBG("Register MMIO region: 0x%llx@%016llx\n", size, offset); + + return 0; +} + +static int e1000e_rx_queue_register(pktio_ops_e1000e_data_t *pkt_e1000e, + uint64_t offset, uint64_t size) +{ + uint16_t rxq_idx = pkt_e1000e->capa.max_input_queues++; + e1000e_rx_queue_t *rxq = &pkt_e1000e->rx_queues[rxq_idx]; + struct ethtool_ringparam ering; + int ret; + + ODP_ASSERT(rxq_idx < ARRAY_SIZE(pkt_e1000e->rx_queues)); + + odp_ticketlock_init(&rxq->lock); + + ret = ethtool_ringparam_get_fd(pkt_e1000e->sockfd, + pkt_e1000e->mdev.if_name, &ering); + if (ret) { + ODP_ERR("Cannot get queue length\n"); + return -1; + } + rxq->rx_queue_len = ering.rx_pending; + + rxq->doorbell = + (odp_u32le_t *)(void *)(pkt_e1000e->mmio + E1000_RDT_OFFSET);
Comment: We have the various `odpdrv_mmio_uxx_read/write()` APIs. Should we also have `_addr` variants that would similarly enable address loading to handle this sort of awkward casting? E.g.: ``` rxq->doorbell = odpdrv_u32le_addr(pkt_e100e->mmio + E1000_RDT_OFFSET); ``` Similar comments for other address setups contained here. > Bill Fischofer(Bill-Fischofer-Linaro) wrote: > Might be good to document where the various "magic numbers" come from. > Presumably from some hardware manual? Does Intel provide a `.h` file that we > can reference/`#include` for these rather than duplicate them here? >> Bill Fischofer(Bill-Fischofer-Linaro) wrote: >> Agree with @muvarov. `_ODP_MDEV` is fine here. The `ODP` prefix should be >> reserved for things that are part of the external ODP API. >>> muvarov wrote >>> place type out of for(). checkpatch should warn about that. >>>> muvarov wrote >>>> please keep ODP_ and odp_ prefix only for odp api. Internal things should >>>> be named as _ODP_ or without that prefix. This comment not just for this >>>> commit but it has to be corrected. https://github.com/Linaro/odp/pull/408#discussion_r163095440 updated_at 2018-01-22 23:13:19