From: John Fastabend <john.fastabend@gmail.com>
To: netdev@vger.kernel.org
Cc: danny.zhou@intel.com, nhorman@tuxdriver.com, dborkman@redhat.com,
john.ronciak@intel.com, hannes@stressinduktion.org,
brouer@redhat.com
Subject: [RFC PATCH v2 2/2] net: ixgbe: implement af_packet direct queue mappings
Date: Mon, 12 Jan 2015 20:35:44 -0800 [thread overview]
Message-ID: <20150113043542.29985.15658.stgit@nitbit.x32> (raw)
In-Reply-To: <20150113043509.29985.33515.stgit@nitbit.x32>
This allows driver queues to be split off and mapped into user
space using af_packet.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 17 +
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 23 +
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 407 ++++++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1
4 files changed, 440 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 38fc64c..aa4960e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -204,6 +204,20 @@ struct ixgbe_tx_queue_stats {
u64 tx_done_old;
};
+#define MAX_USER_DMA_REGIONS_PER_SOCKET 16
+
+struct ixgbe_user_dma_region {
+ dma_addr_t dma_region_iova;
+ unsigned long dma_region_size;
+ int direction;
+};
+
+struct ixgbe_user_queue_info {
+ struct sock *sk_handle;
+ struct ixgbe_user_dma_region regions[MAX_USER_DMA_REGIONS_PER_SOCKET];
+ int num_of_regions;
+};
+
struct ixgbe_rx_queue_stats {
u64 rsc_count;
u64 rsc_flush;
@@ -673,6 +687,9 @@ struct ixgbe_adapter {
struct ixgbe_q_vector *q_vector[MAX_Q_VECTORS];
+ /* Direct User Space Queues */
+ struct ixgbe_user_queue_info user_queue_info[MAX_RX_QUEUES];
+
/* DCB parameters */
struct ieee_pfc *ixgbe_ieee_pfc;
struct ieee_ets *ixgbe_ieee_ets;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index e5be0dd..f180a58 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2598,12 +2598,17 @@ static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
return -EOPNOTSUPP;
+ if (fsp->ring_cookie > MAX_RX_QUEUES)
+ return -EINVAL;
+
/*
* Don't allow programming if the action is a queue greater than
- * the number of online Rx queues.
+ * the number of online Rx queues unless it is a user space
+ * queue.
*/
if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
- (fsp->ring_cookie >= adapter->num_rx_queues))
+ (fsp->ring_cookie >= adapter->num_rx_queues) &&
+ !adapter->user_queue_info[fsp->ring_cookie].sk_handle)
return -EINVAL;
/* Don't allow indexes to exist outside of available space */
@@ -2680,12 +2685,18 @@ static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
/* apply mask and compute/store hash */
ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
+ /* Set input action to reg_idx for driver owned queues otherwise
+ * use the absolute index for user space queues.
+ */
+ if (fsp->ring_cookie < adapter->num_rx_queues &&
+ fsp->ring_cookie != IXGBE_FDIR_DROP_QUEUE)
+ input->action = adapter->rx_ring[input->action]->reg_idx;
+
/* program filters to filter memory */
err = ixgbe_fdir_write_perfect_filter_82599(hw,
- &input->filter, input->sw_idx,
- (input->action == IXGBE_FDIR_DROP_QUEUE) ?
- IXGBE_FDIR_DROP_QUEUE :
- adapter->rx_ring[input->action]->reg_idx);
+ &input->filter,
+ input->sw_idx,
+ input->action);
if (err)
goto err_out_w_lock;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 2ed2c7d..be5bde86 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -50,6 +50,9 @@
#include <linux/if_bridge.h>
#include <linux/prefetch.h>
#include <scsi/fc/fc_fcoe.h>
+#include <linux/mm.h>
+#include <linux/if_packet.h>
+#include <linux/iommu.h>
#ifdef CONFIG_OF
#include <linux/of_net.h>
@@ -80,6 +83,12 @@ const char ixgbe_driver_version[] = DRV_VERSION;
static const char ixgbe_copyright[] =
"Copyright (c) 1999-2014 Intel Corporation.";
+static unsigned int *dummy_page_buf;
+
+#ifndef CONFIG_DMA_MEMORY_PROTECTION
+#define CONFIG_DMA_MEMORY_PROTECTION
+#endif
+
static const struct ixgbe_info *ixgbe_info_tbl[] = {
[board_82598] = &ixgbe_82598_info,
[board_82599] = &ixgbe_82599_info,
@@ -167,6 +176,76 @@ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+enum ixgbe_legacy_rx_enum {
+ IXGBE_LEGACY_RX_FIELD_PKT_ADDR = 0, /* Packet buffer address */
+ IXGBE_LEGACY_RX_FIELD_LENGTH, /* Packet length */
+ IXGBE_LEGACY_RX_FIELD_CSUM, /* Fragment checksum */
+ IXGBE_LEGACY_RX_FIELD_STATUS, /* Descriptors status */
+ IXGBE_LEGACY_RX_FIELD_ERRORS, /* Receive errors */
+ IXGBE_LEGACY_RX_FIELD_VLAN, /* VLAN tag */
+};
+
+enum ixgbe_legacy_tx_enum {
+ IXGBE_LEGACY_TX_FIELD_PKT_ADDR = 0, /* Packet buffer address */
+ IXGBE_LEGACY_TX_FIELD_LENGTH, /* Packet length */
+ IXGBE_LEGACY_TX_FIELD_CSO, /* Checksum offset*/
+ IXGBE_LEGACY_TX_FIELD_CMD, /* Descriptor control */
+ IXGBE_LEGACY_TX_FIELD_STATUS, /* Descriptor status */
+ IXGBE_LEGACY_TX_FIELD_RSVD, /* Reserved */
+ IXGBE_LEGACY_TX_FIELD_CSS, /* Checksum start */
+ IXGBE_LEGACY_TX_FIELD_VLAN_TAG, /* VLAN tag */
+};
+
+/* IXGBE Receive Descriptor - Legacy */
+static const struct tpacket_nic_desc_fld ixgbe_legacy_rx_desc[] = {
+ /* Packet buffer address */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_RX_FIELD_PKT_ADDR,
+ 0, 64, 64, BO_NATIVE)},
+ /* Packet length */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_RX_FIELD_LENGTH,
+ 64, 16, 8, BO_NATIVE)},
+ /* Fragment checksum */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_RX_FIELD_CSUM,
+ 80, 16, 8, BO_NATIVE)},
+ /* Descriptors status */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_RX_FIELD_STATUS,
+ 96, 8, 8, BO_NATIVE)},
+ /* Receive errors */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_RX_FIELD_ERRORS,
+ 104, 8, 8, BO_NATIVE)},
+ /* VLAN tag */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_RX_FIELD_VLAN,
+ 112, 16, 8, BO_NATIVE)},
+};
+
+/* IXGBE Transmit Descriptor - Legacy */
+static const struct tpacket_nic_desc_fld ixgbe_legacy_tx_desc[] = {
+ /* Packet buffer address */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_PKT_ADDR,
+ 0, 64, 64, BO_NATIVE)},
+ /* Data buffer length */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_LENGTH,
+ 64, 16, 8, BO_NATIVE)},
+ /* Checksum offset */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_CSO,
+ 80, 8, 8, BO_NATIVE)},
+ /* Command byte */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_CMD,
+ 88, 8, 8, BO_NATIVE)},
+ /* Transmitted status */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_STATUS,
+ 96, 4, 1, BO_NATIVE)},
+ /* Reserved */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_RSVD,
+ 100, 4, 1, BO_NATIVE)},
+ /* Checksum start */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_CSS,
+ 104, 8, 8, BO_NATIVE)},
+ /* VLAN tag */
+ {PACKET_NIC_DESC_FIELD(IXGBE_LEGACY_TX_FIELD_VLAN_TAG,
+ 112, 16, 8, BO_NATIVE)},
+};
+
static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
@@ -3137,6 +3216,17 @@ static void ixgbe_enable_rx_drop(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl);
}
+static bool ixgbe_have_user_queues(struct ixgbe_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < MAX_RX_QUEUES; i++) {
+ if (adapter->user_queue_info[i].sk_handle)
+ return true;
+ }
+ return false;
+}
+
static void ixgbe_disable_rx_drop(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring)
{
@@ -3171,7 +3261,8 @@ static void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter)
* and performance reasons.
*/
if (adapter->num_vfs || (adapter->num_rx_queues > 1 &&
- !(adapter->hw.fc.current_mode & ixgbe_fc_tx_pause) && !pfc_en)) {
+ !(adapter->hw.fc.current_mode & ixgbe_fc_tx_pause) && !pfc_en) ||
+ ixgbe_have_user_queues(adapter)) {
for (i = 0; i < adapter->num_rx_queues; i++)
ixgbe_enable_rx_drop(adapter, adapter->rx_ring[i]);
} else {
@@ -7938,6 +8029,306 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
kfree(fwd_adapter);
}
+static int ixgbe_ndo_split_queue_pairs(struct net_device *dev,
+ unsigned int start_from,
+ unsigned int qpairs_num,
+ struct sock *sk)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ unsigned int qpair_index;
+
+ /* allocate whatever available qpairs */
+ if (start_from == -1) {
+ unsigned int count = 0;
+
+ for (qpair_index = adapter->num_rx_queues;
+ qpair_index < MAX_RX_QUEUES;
+ qpair_index++) {
+ if (!adapter->user_queue_info[qpair_index].sk_handle) {
+ count++;
+ if (count == qpairs_num) {
+ start_from = qpair_index - count + 1;
+ break;
+ }
+ } else {
+ count = 0;
+ }
+ }
+ }
+
+ /* otherwise the caller specified exact queues */
+ if ((start_from > MAX_TX_QUEUES) ||
+ (start_from > MAX_RX_QUEUES) ||
+ (start_from + qpairs_num > MAX_TX_QUEUES) ||
+ (start_from + qpairs_num > MAX_RX_QUEUES))
+ return -EINVAL;
+
+ /* If the qpairs are being used by the driver do not let user space
+ * consume the queues. Also if the queue has already been allocated
+ * to a socket do fail the request.
+ */
+ for (qpair_index = start_from;
+ qpair_index < start_from + qpairs_num;
+ qpair_index++) {
+ if ((qpair_index < adapter->num_tx_queues) ||
+ (qpair_index < adapter->num_rx_queues))
+ return -EINVAL;
+
+ if (adapter->user_queue_info[qpair_index].sk_handle)
+ return -EBUSY;
+ }
+
+ /* remember the sk handle for each queue pair */
+ for (qpair_index = start_from;
+ qpair_index < start_from + qpairs_num;
+ qpair_index++) {
+ adapter->user_queue_info[qpair_index].sk_handle = sk;
+ adapter->user_queue_info[qpair_index].num_of_regions = 0;
+ }
+
+ return 0;
+}
+
+static int ixgbe_ndo_get_split_queue_pairs(struct net_device *dev,
+ unsigned int *start_from,
+ unsigned int *qpairs_num,
+ struct sock *sk)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ unsigned int qpair_index;
+ *qpairs_num = 0;
+
+ for (qpair_index = adapter->num_tx_queues;
+ qpair_index < MAX_RX_QUEUES;
+ qpair_index++) {
+ if (adapter->user_queue_info[qpair_index].sk_handle == sk) {
+ if (*qpairs_num == 0)
+ *start_from = qpair_index;
+ *qpairs_num = *qpairs_num + 1;
+ }
+ }
+
+ return 0;
+}
+
+static int ixgbe_ndo_return_queue_pairs(struct net_device *dev, struct sock *sk)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ struct ixgbe_user_queue_info *info;
+ unsigned int qpair_index;
+
+ for (qpair_index = adapter->num_tx_queues;
+ qpair_index < MAX_RX_QUEUES;
+ qpair_index++) {
+ info = &adapter->user_queue_info[qpair_index];
+
+ if (info->sk_handle == sk) {
+ info->sk_handle = NULL;
+ info->num_of_regions = 0;
+ }
+ }
+
+ return 0;
+}
+
+/* Rx descriptor starts from 0x1000 and Tx descriptor starts from 0x6000
+ * both the TX and RX descriptors use 4K pages.
+ */
+#define RX_DESC_ADDR_OFFSET 0x1000
+#define TX_DESC_ADDR_OFFSET 0x6000
+#define PAGE_SIZE_4K 4096
+
+static int
+ixgbe_ndo_qpair_map_region(struct net_device *dev,
+ struct tpacket_dev_qpair_map_region_info *info)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ /* no need to map systme memory to userspace for ixgbe */
+ info->tp_dev_sysm_sz = 0;
+ info->tp_num_sysm_map_regions = 0;
+
+ info->tp_dev_bar_sz = pci_resource_len(adapter->pdev, 0);
+ info->tp_num_map_regions = 2;
+
+ info->tp_regions[0].page_offset = RX_DESC_ADDR_OFFSET;
+ info->tp_regions[0].page_sz = PAGE_SIZE;
+ info->tp_regions[0].page_cnt = 1;
+ info->tp_regions[1].page_offset = TX_DESC_ADDR_OFFSET;
+ info->tp_regions[1].page_sz = PAGE_SIZE;
+ info->tp_regions[1].page_cnt = 1;
+
+ return 0;
+}
+
+static int ixgbe_ndo_get_device_desc_info(struct net_device *dev,
+ struct tpacket_dev_info *dev_info)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int max_queues;
+ int i;
+ __u8 flds_rx = sizeof(ixgbe_legacy_rx_desc) /
+ sizeof(struct tpacket_nic_desc_fld);
+ __u8 flds_tx = sizeof(ixgbe_legacy_tx_desc) /
+ sizeof(struct tpacket_nic_desc_fld);
+
+ max_queues = max(adapter->num_rx_queues, adapter->num_tx_queues);
+
+ dev_info->tp_device_id = adapter->hw.device_id;
+ dev_info->tp_vendor_id = adapter->hw.vendor_id;
+ dev_info->tp_subsystem_device_id = adapter->hw.subsystem_device_id;
+ dev_info->tp_subsystem_vendor_id = adapter->hw.subsystem_vendor_id;
+ dev_info->tp_revision_id = adapter->hw.revision_id;
+ dev_info->tp_numa_node = dev_to_node(&dev->dev);
+
+ dev_info->tp_num_total_qpairs = min(MAX_RX_QUEUES, MAX_TX_QUEUES);
+ dev_info->tp_num_inuse_qpairs = max_queues;
+
+ dev_info->tp_num_rx_desc_fmt = 1;
+ dev_info->tp_num_tx_desc_fmt = 1;
+
+ dev_info->tp_rx_dexpr[0].version = 1;
+ dev_info->tp_rx_dexpr[0].size = sizeof(union ixgbe_adv_rx_desc);
+ dev_info->tp_rx_dexpr[0].byte_order = BO_NATIVE;
+ dev_info->tp_rx_dexpr[0].num_of_fld = flds_rx;
+ for (i = 0; i < dev_info->tp_rx_dexpr[0].num_of_fld; i++)
+ memcpy(&dev_info->tp_rx_dexpr[0].fields[i],
+ &ixgbe_legacy_rx_desc[i],
+ sizeof(struct tpacket_nic_desc_fld));
+
+ dev_info->tp_tx_dexpr[0].version = 1;
+ dev_info->tp_tx_dexpr[0].size = sizeof(union ixgbe_adv_tx_desc);
+ dev_info->tp_tx_dexpr[0].byte_order = BO_NATIVE;
+ dev_info->tp_tx_dexpr[0].num_of_fld = flds_tx;
+ for (i = 0; i < dev_info->tp_rx_dexpr[0].num_of_fld; i++)
+ memcpy(&dev_info->tp_tx_dexpr[0].fields[i],
+ &ixgbe_legacy_tx_desc[i],
+ sizeof(struct tpacket_nic_desc_fld));
+
+ return 0;
+}
+
+static int
+ixgbe_ndo_qpair_page_map(struct vm_area_struct *vma, struct net_device *dev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ phys_addr_t phy_addr = pci_resource_start(adapter->pdev, 0);
+ unsigned long pfn_rx = (phy_addr + RX_DESC_ADDR_OFFSET) >> PAGE_SHIFT;
+ unsigned long pfn_tx = (phy_addr + TX_DESC_ADDR_OFFSET) >> PAGE_SHIFT;
+ unsigned long dummy_page_phy;
+ pgprot_t pre_vm_page_prot;
+ unsigned long start;
+ unsigned int i;
+ int err;
+
+ if (!dummy_page_buf) {
+ dummy_page_buf = kzalloc(PAGE_SIZE_4K, GFP_KERNEL);
+ if (!dummy_page_buf)
+ return -ENOMEM;
+
+ for (i = 0; i < PAGE_SIZE_4K / sizeof(unsigned int); i++)
+ dummy_page_buf[i] = 0xdeadbeef;
+ }
+
+ dummy_page_phy = virt_to_phys(dummy_page_buf);
+ pre_vm_page_prot = vma->vm_page_prot;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ /* assume the vm_start is 4K aligned address */
+ for (start = vma->vm_start;
+ start < vma->vm_end;
+ start += PAGE_SIZE_4K) {
+ if (start == vma->vm_start + RX_DESC_ADDR_OFFSET) {
+ err = remap_pfn_range(vma, start, pfn_rx, PAGE_SIZE_4K,
+ vma->vm_page_prot);
+ if (err)
+ return -EAGAIN;
+ } else if (start == vma->vm_start + TX_DESC_ADDR_OFFSET) {
+ err = remap_pfn_range(vma, start, pfn_tx, PAGE_SIZE_4K,
+ vma->vm_page_prot);
+ if (err)
+ return -EAGAIN;
+ } else {
+ unsigned long addr = dummy_page_phy > PAGE_SHIFT;
+
+ err = remap_pfn_range(vma, start, addr, PAGE_SIZE_4K,
+ pre_vm_page_prot);
+ if (err)
+ return -EAGAIN;
+ }
+ }
+ return 0;
+}
+
+static int
+ixgbe_ndo_val_dma_mem_region_map(struct net_device *dev,
+ struct tpacket_dma_mem_region *region,
+ struct sock *sk)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ unsigned int qpair_index, i;
+ struct ixgbe_user_queue_info *info;
+
+#ifdef CONFIG_DMA_MEMORY_PROTECTION
+ /* IOVA not equal to physical address means IOMMU takes effect */
+ if (region->phys_addr == region->iova)
+ return -EFAULT;
+#endif
+
+ for (qpair_index = adapter->num_tx_queues;
+ qpair_index < MAX_RX_QUEUES;
+ qpair_index++) {
+ info = &adapter->user_queue_info[qpair_index];
+ i = info->num_of_regions;
+
+ if (info->sk_handle != sk)
+ continue;
+
+ if (info->num_of_regions >= MAX_USER_DMA_REGIONS_PER_SOCKET)
+ return -EFAULT;
+
+ info->regions[i].dma_region_size = region->size;
+ info->regions[i].direction = region->direction;
+ info->regions[i].dma_region_iova = region->iova;
+ info->num_of_regions++;
+ }
+
+ return 0;
+}
+
+static int
+ixgbe_get_dma_region_info(struct net_device *dev,
+ struct tpacket_dma_mem_region *region,
+ struct sock *sk)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ struct ixgbe_user_queue_info *info;
+ unsigned int qpair_index;
+
+ for (qpair_index = adapter->num_tx_queues;
+ qpair_index < MAX_RX_QUEUES;
+ qpair_index++) {
+ int i;
+
+ info = &adapter->user_queue_info[qpair_index];
+ if (info->sk_handle != sk)
+ continue;
+
+ for (i = 0; i <= info->num_of_regions; i++) {
+ struct ixgbe_user_dma_region *r;
+
+ r = &info->regions[i];
+ if ((r->dma_region_size == region->size) &&
+ (r->direction == region->direction)) {
+ region->iova = r->dma_region_iova;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
@@ -7982,6 +8373,15 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_bridge_getlink = ixgbe_ndo_bridge_getlink,
.ndo_dfwd_add_station = ixgbe_fwd_add,
.ndo_dfwd_del_station = ixgbe_fwd_del,
+
+ .ndo_split_queue_pairs = ixgbe_ndo_split_queue_pairs,
+ .ndo_get_split_queue_pairs = ixgbe_ndo_get_split_queue_pairs,
+ .ndo_return_queue_pairs = ixgbe_ndo_return_queue_pairs,
+ .ndo_get_device_desc_info = ixgbe_ndo_get_device_desc_info,
+ .ndo_direct_qpair_page_map = ixgbe_ndo_qpair_page_map,
+ .ndo_get_dma_region_info = ixgbe_get_dma_region_info,
+ .ndo_get_device_qpair_map_region_info = ixgbe_ndo_qpair_map_region,
+ .ndo_validate_dma_mem_region_map = ixgbe_ndo_val_dma_mem_region_map,
};
/**
@@ -8203,7 +8603,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->back = adapter;
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
- hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
+ hw->pci_hw_addr = pci_resource_start(pdev, 0);
+
+ hw->hw_addr = ioremap(hw->pci_hw_addr,
pci_resource_len(pdev, 0));
adapter->io_addr = hw->hw_addr;
if (!hw->hw_addr) {
@@ -8875,6 +9277,7 @@ module_init(ixgbe_init_module);
**/
static void __exit ixgbe_exit_module(void)
{
+ kfree(dummy_page_buf);
#ifdef CONFIG_IXGBE_DCA
dca_unregister_notify(&dca_notifier);
#endif
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index d101b25..4034d31 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -3180,6 +3180,7 @@ struct ixgbe_mbx_info {
struct ixgbe_hw {
u8 __iomem *hw_addr;
+ phys_addr_t pci_hw_addr;
void *back;
struct ixgbe_mac_info mac;
struct ixgbe_addr_filter_info addr_ctrl;
next prev parent reply other threads:[~2015-01-13 4:36 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-13 4:35 [RFC PATCH v2 1/2] net: af_packet support for direct ring access in user space John Fastabend
2015-01-13 4:35 ` John Fastabend [this message]
2015-01-13 12:05 ` [RFC PATCH v2 2/2] net: ixgbe: implement af_packet direct queue mappings Hannes Frederic Sowa
2015-01-13 14:26 ` Daniel Borkmann
2015-01-13 15:46 ` John Fastabend
2015-01-13 18:18 ` Daniel Borkmann
2015-01-13 18:58 ` Willem de Bruijn
2015-01-13 4:42 ` [RFC PATCH v2 1/2] net: af_packet support for direct ring access in user space John Fastabend
2015-01-13 12:35 ` Hannes Frederic Sowa
2015-01-13 13:21 ` Daniel Borkmann
2015-01-13 15:24 ` John Fastabend
2015-01-13 17:15 ` David Laight
2015-01-13 17:27 ` David Miller
2015-01-14 15:28 ` Zhou, Danny
2015-01-13 15:12 ` Daniel Borkmann
2015-01-13 15:58 ` John Fastabend
2015-01-13 16:05 ` Daniel Borkmann
2015-01-13 16:19 ` Neil Horman
2015-01-13 18:52 ` Willem de Bruijn
2015-01-14 15:26 ` Zhou, Danny
2015-01-14 20:35 ` David Miller
2015-01-17 17:35 ` John Fastabend
2015-01-18 22:02 ` Neil Horman
2015-01-19 21:45 ` Neil Horman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150113043542.29985.15658.stgit@nitbit.x32 \
--to=john.fastabend@gmail.com \
--cc=brouer@redhat.com \
--cc=danny.zhou@intel.com \
--cc=dborkman@redhat.com \
--cc=hannes@stressinduktion.org \
--cc=john.ronciak@intel.com \
--cc=netdev@vger.kernel.org \
--cc=nhorman@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.