diff mbox

[dpdk-dev,3/5] net/szedata2: refactor ibuf and obuf address definition

Message ID 1495821956-5050-3-git-send-email-vido@cesnet.cz (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers show

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Matej Vido May 26, 2017, 6:05 p.m. UTC
This is to prepare for firmwares with multiple ibufs and obufs.
Offsets of ibufs and obufs are defined in array.
Functions which operate on ibufs and obufs iterate over this array.

Signed-off-by: Matej Vido <vido@cesnet.cz>
---
 drivers/net/szedata2/Makefile           |    1 +
 drivers/net/szedata2/rte_eth_szedata2.c |  121 +++++++++++++++++++++----------
 drivers/net/szedata2/rte_eth_szedata2.h |   64 ----------------
 drivers/net/szedata2/szedata2_iobuf.c   |   69 ++++++++++++++++++
 drivers/net/szedata2/szedata2_iobuf.h   |   95 ++++++++++++++++++++++++
 5 files changed, 246 insertions(+), 104 deletions(-)
 create mode 100644 drivers/net/szedata2/szedata2_iobuf.c
 create mode 100644 drivers/net/szedata2/szedata2_iobuf.h

Comments

Ferruh Yigit May 29, 2017, 12:41 p.m. UTC | #1
On 5/26/2017 7:05 PM, Matej Vido wrote:
> This is to prepare for firmwares with multiple ibufs and obufs.
> Offsets of ibufs and obufs are defined in array.

I was thinking ibufs and obufs as queues, but since link functions
updated per ibufs it looks like ports, can you please provide some
information what is ibufs and obufs?

What is the benefit of having multiple ibufs and obufs?

> Functions which operate on ibufs and obufs iterate over this array.
> 
> Signed-off-by: Matej Vido <vido@cesnet.cz>
<...>
Matej Vido May 31, 2017, 8:33 a.m. UTC | #2
On 29.05.2017 14:41, Ferruh Yigit wrote:
> On 5/26/2017 7:05 PM, Matej Vido wrote:
>> This is to prepare for firmwares with multiple ibufs and obufs.
>> Offsets of ibufs and obufs are defined in array.
> I was thinking ibufs and obufs as queues, but since link functions
> updated per ibufs it looks like ports, can you please provide some
> information what is ibufs and obufs?
>
> What is the benefit of having multiple ibufs and obufs?
Hi Ferruh,

ibufs and obufs are the modules in FPGA firmware implementing the 
Ethernet port (MAC layer, to be exact). There is one ibuf+obuf per 
Ethernet port. Our cards and firmwares allow one 100GE physical port to 
be one Ethernet port, or split into 10 ports of 10GE. However, all DMA 
queues in the device are shared between all Ethernet ports. Packet from 
any port can be passed by crossbar logic to any DMA queue (and from any 
DMA queue to any port).

Regards,
Matej
>
>> Functions which operate on ibufs and obufs iterate over this array.
>>
>> Signed-off-by: Matej Vido <vido@cesnet.cz>
> <...>
Ferruh Yigit May 31, 2017, 9:12 a.m. UTC | #3
On 5/31/2017 9:33 AM, Matej Vido wrote:
> On 29.05.2017 14:41, Ferruh Yigit wrote:
>> On 5/26/2017 7:05 PM, Matej Vido wrote:
>>> This is to prepare for firmwares with multiple ibufs and obufs.
>>> Offsets of ibufs and obufs are defined in array.
>> I was thinking ibufs and obufs as queues, but since link functions
>> updated per ibufs it looks like ports, can you please provide some
>> information what is ibufs and obufs?
>>
>> What is the benefit of having multiple ibufs and obufs?
> Hi Ferruh,
> 
> ibufs and obufs are the modules in FPGA firmware implementing the 
> Ethernet port (MAC layer, to be exact). There is one ibuf+obuf per 
> Ethernet port. Our cards and firmwares allow one 100GE physical port to 
> be one Ethernet port, or split into 10 ports of 10GE. However, all DMA 
> queues in the device are shared between all Ethernet ports. Packet from 
> any port can be passed by crossbar logic to any DMA queue (and from any 
> DMA queue to any port).

Thank you for clarification.

> 
> Regards,
> Matej
>>
>>> Functions which operate on ibufs and obufs iterate over this array.
>>>
>>> Signed-off-by: Matej Vido <vido@cesnet.cz>
>> <...>
>
diff mbox

Patch

diff --git a/drivers/net/szedata2/Makefile b/drivers/net/szedata2/Makefile
index 836c3b2..0e96b92 100644
--- a/drivers/net/szedata2/Makefile
+++ b/drivers/net/szedata2/Makefile
@@ -48,6 +48,7 @@  LIBABIVER := 1
 # all source are stored in SRCS-y
 #
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += rte_eth_szedata2.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2_iobuf.c
 
 #
 # Export include files
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index f8ec331..49495fd 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -53,6 +53,7 @@ 
 #include <rte_atomic.h>
 
 #include "rte_eth_szedata2.h"
+#include "szedata2_iobuf.h"
 
 #define RTE_ETH_SZEDATA2_MAX_RX_QUEUES 32
 #define RTE_ETH_SZEDATA2_MAX_TX_QUEUES 32
@@ -1140,6 +1141,33 @@  struct pmd_internals {
 	dev->data->nb_tx_queues = 0;
 }
 
+/**
+ * Function takes value from first IBUF status register.
+ * Values in IBUF and OBUF should be same.
+ *
+ * @param internals
+ *     Pointer to device private structure.
+ * @return
+ *     Link speed constant.
+ */
+static inline enum szedata2_link_speed
+get_link_speed(const struct pmd_internals *internals)
+{
+	const volatile struct szedata2_ibuf *ibuf =
+		ibuf_ptr_by_index(internals->pci_rsc, 0);
+	uint32_t speed = (szedata2_read32(&ibuf->ibuf_st) & 0x70) >> 4;
+	switch (speed) {
+	case 0x03:
+		return SZEDATA2_LINK_SPEED_10G;
+	case 0x04:
+		return SZEDATA2_LINK_SPEED_40G;
+	case 0x05:
+		return SZEDATA2_LINK_SPEED_100G;
+	default:
+		return SZEDATA2_LINK_SPEED_DEFAULT;
+	}
+}
+
 static int
 eth_link_update(struct rte_eth_dev *dev,
 		int wait_to_complete __rte_unused)
@@ -1149,11 +1177,11 @@  struct pmd_internals {
 	struct rte_eth_link *dev_link = &dev->data->dev_link;
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	const volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			const volatile struct szedata2_ibuf *);
+	const volatile struct szedata2_ibuf *ibuf;
+	uint32_t i;
+	bool link_is_up = false;
 
-	switch (get_link_speed(ibuf)) {
+	switch (get_link_speed(internals)) {
 	case SZEDATA2_LINK_SPEED_10G:
 		link.link_speed = ETH_SPEED_NUM_10G;
 		break;
@@ -1171,8 +1199,19 @@  struct pmd_internals {
 	/* szedata2 uses only full duplex */
 	link.link_duplex = ETH_LINK_FULL_DUPLEX;
 
-	link.link_status = (ibuf_is_enabled(ibuf) &&
-			ibuf_is_link_up(ibuf)) ? ETH_LINK_UP : ETH_LINK_DOWN;
+	for (i = 0; i < szedata2_ibuf_count; i++) {
+		ibuf = ibuf_ptr_by_index(internals->pci_rsc, i);
+		/*
+		 * Link is considered up if at least one ibuf is enabled
+		 * and up.
+		 */
+		if (ibuf_is_enabled(ibuf) && ibuf_is_link_up(ibuf)) {
+			link_is_up = true;
+			break;
+		}
+	}
+
+	link.link_status = (link_is_up) ? ETH_LINK_UP : ETH_LINK_DOWN;
 
 	link.link_autoneg = ETH_LINK_SPEED_FIXED;
 
@@ -1187,15 +1226,12 @@  struct pmd_internals {
 {
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			volatile struct szedata2_ibuf *);
-	volatile struct szedata2_obuf *obuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_OBUF_BASE_OFF,
-			volatile struct szedata2_obuf *);
-
-	ibuf_enable(ibuf);
-	obuf_enable(obuf);
+	uint32_t i;
+
+	for (i = 0; i < szedata2_ibuf_count; i++)
+		ibuf_enable(ibuf_ptr_by_index(internals->pci_rsc, i));
+	for (i = 0; i < szedata2_obuf_count; i++)
+		obuf_enable(obuf_ptr_by_index(internals->pci_rsc, i));
 	return 0;
 }
 
@@ -1204,15 +1240,12 @@  struct pmd_internals {
 {
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			volatile struct szedata2_ibuf *);
-	volatile struct szedata2_obuf *obuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_OBUF_BASE_OFF,
-			volatile struct szedata2_obuf *);
-
-	ibuf_disable(ibuf);
-	obuf_disable(obuf);
+	uint32_t i;
+
+	for (i = 0; i < szedata2_ibuf_count; i++)
+		ibuf_disable(ibuf_ptr_by_index(internals->pci_rsc, i));
+	for (i = 0; i < szedata2_obuf_count; i++)
+		obuf_disable(obuf_ptr_by_index(internals->pci_rsc, i));
 	return 0;
 }
 
@@ -1292,10 +1325,12 @@  struct pmd_internals {
 {
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			volatile struct szedata2_ibuf *);
-	ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_PROMISC);
+	uint32_t i;
+
+	for (i = 0; i < szedata2_ibuf_count; i++) {
+		ibuf_mac_mode_write(ibuf_ptr_by_index(internals->pci_rsc, i),
+				SZEDATA2_MAC_CHMODE_PROMISC);
+	}
 }
 
 static void
@@ -1303,10 +1338,12 @@  struct pmd_internals {
 {
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			volatile struct szedata2_ibuf *);
-	ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_ONLY_VALID);
+	uint32_t i;
+
+	for (i = 0; i < szedata2_ibuf_count; i++) {
+		ibuf_mac_mode_write(ibuf_ptr_by_index(internals->pci_rsc, i),
+				SZEDATA2_MAC_CHMODE_ONLY_VALID);
+	}
 }
 
 static void
@@ -1314,10 +1351,12 @@  struct pmd_internals {
 {
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			volatile struct szedata2_ibuf *);
-	ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_ALL_MULTICAST);
+	uint32_t i;
+
+	for (i = 0; i < szedata2_ibuf_count; i++) {
+		ibuf_mac_mode_write(ibuf_ptr_by_index(internals->pci_rsc, i),
+				SZEDATA2_MAC_CHMODE_ALL_MULTICAST);
+	}
 }
 
 static void
@@ -1325,10 +1364,12 @@  struct pmd_internals {
 {
 	struct pmd_internals *internals = (struct pmd_internals *)
 		dev->data->dev_private;
-	volatile struct szedata2_ibuf *ibuf = SZEDATA2_PCI_RESOURCE_PTR(
-			internals->pci_rsc, SZEDATA2_IBUF_BASE_OFF,
-			volatile struct szedata2_ibuf *);
-	ibuf_mac_mode_write(ibuf, SZEDATA2_MAC_CHMODE_ONLY_VALID);
+	uint32_t i;
+
+	for (i = 0; i < szedata2_ibuf_count; i++) {
+		ibuf_mac_mode_write(ibuf_ptr_by_index(internals->pci_rsc, i),
+				SZEDATA2_MAC_CHMODE_ONLY_VALID);
+	}
 }
 
 static const struct eth_dev_ops ops = {
diff --git a/drivers/net/szedata2/rte_eth_szedata2.h b/drivers/net/szedata2/rte_eth_szedata2.h
index 0b635d0..6b31a77 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.h
+++ b/drivers/net/szedata2/rte_eth_szedata2.h
@@ -126,9 +126,6 @@  struct szedata {
 	rte_write32(rte_cpu_to_le_32(value), addr);
 }
 
-#define SZEDATA2_PCI_RESOURCE_PTR(rsc, offset, type) \
-	((type)(((uint8_t *)(rsc)->addr) + (offset)))
-
 enum szedata2_link_speed {
 	SZEDATA2_LINK_SPEED_DEFAULT = 0,
 	SZEDATA2_LINK_SPEED_10G,
@@ -326,65 +323,4 @@  struct szedata2_obuf {
 			&obuf->obuf_en);
 }
 
-/*
- * Function takes value from IBUF status register. Values in IBUF and OBUF
- * should be same.
- *
- * @return Link speed constant.
- */
-static inline enum szedata2_link_speed
-get_link_speed(const volatile struct szedata2_ibuf *ibuf)
-{
-	uint32_t speed = (szedata2_read32(&ibuf->ibuf_st) & 0x70) >> 4;
-	switch (speed) {
-	case 0x03:
-		return SZEDATA2_LINK_SPEED_10G;
-	case 0x04:
-		return SZEDATA2_LINK_SPEED_40G;
-	case 0x05:
-		return SZEDATA2_LINK_SPEED_100G;
-	default:
-		return SZEDATA2_LINK_SPEED_DEFAULT;
-	}
-}
-
-/*
- * IBUFs and OBUFs can generally be located at different offsets in different
- * firmwares.
- * This part defines base offsets of IBUFs and OBUFs through various firmwares.
- * Currently one firmware type is supported.
- * Type of firmware is set through configuration option
- * CONFIG_RTE_LIBRTE_PMD_SZEDATA_AS.
- * Possible values are:
- * 0 - for firmwares:
- *     NIC_100G1_LR4
- *     HANIC_100G1_LR4
- *     HANIC_100G1_SR10
- */
-#if !defined(RTE_LIBRTE_PMD_SZEDATA2_AS)
-#error "RTE_LIBRTE_PMD_SZEDATA2_AS has to be defined"
-#elif RTE_LIBRTE_PMD_SZEDATA2_AS == 0
-
-/*
- * IBUF offset from the beginning of PCI resource address space.
- */
-#define SZEDATA2_IBUF_BASE_OFF 0x8000
-/*
- * Size of IBUF.
- */
-#define SZEDATA2_IBUF_SIZE 0x200
-
-/*
- * OBUF offset from the beginning of PCI resource address space.
- */
-#define SZEDATA2_OBUF_BASE_OFF 0x9000
-/*
- * Size of OBUF.
- */
-#define SZEDATA2_OBUF_SIZE 0x100
-
-#else
-#error "RTE_LIBRTE_PMD_SZEDATA2_AS has wrong value, see comments in config file"
-#endif
-
 #endif
diff --git a/drivers/net/szedata2/szedata2_iobuf.c b/drivers/net/szedata2/szedata2_iobuf.c
new file mode 100644
index 0000000..2d25e65
--- /dev/null
+++ b/drivers/net/szedata2/szedata2_iobuf.c
@@ -0,0 +1,69 @@ 
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (c) 2017 CESNET
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of CESNET nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rte_common.h>
+
+#include "szedata2_iobuf.h"
+
+/*
+ * IBUFs and OBUFs can generally be located at different offsets in different
+ * firmwares.
+ * This part defines base offsets of IBUFs and OBUFs through various firmwares.
+ * Currently one firmware type is supported.
+ * Type of firmware is set through configuration option
+ * CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS.
+ * Possible values are:
+ * 0 - for firmwares:
+ *     NIC_100G1_LR4
+ *     HANIC_100G1_LR4
+ *     HANIC_100G1_SR10
+ */
+#if !defined(RTE_LIBRTE_PMD_SZEDATA2_AS)
+#error "RTE_LIBRTE_PMD_SZEDATA2_AS has to be defined"
+#elif RTE_LIBRTE_PMD_SZEDATA2_AS == 0
+
+const uint32_t szedata2_ibuf_base_table[] = {
+	0x8000
+};
+const uint32_t szedata2_obuf_base_table[] = {
+	0x9000
+};
+
+#else
+#error "RTE_LIBRTE_PMD_SZEDATA2_AS has wrong value, see comments in config file"
+#endif
+
+const uint32_t szedata2_ibuf_count = RTE_DIM(szedata2_ibuf_base_table);
+const uint32_t szedata2_obuf_count = RTE_DIM(szedata2_obuf_base_table);
diff --git a/drivers/net/szedata2/szedata2_iobuf.h b/drivers/net/szedata2/szedata2_iobuf.h
new file mode 100644
index 0000000..3ae4367
--- /dev/null
+++ b/drivers/net/szedata2/szedata2_iobuf.h
@@ -0,0 +1,95 @@ 
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (c) 2017 CESNET
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of CESNET nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SZEDATA2_IOBUF_H_
+#define _SZEDATA2_IOBUF_H_
+
+#include <stdint.h>
+
+#include <rte_dev.h>
+
+/* IBUF offsets from the beginning of the PCI resource address space. */
+extern const uint32_t szedata2_ibuf_base_table[];
+extern const uint32_t szedata2_ibuf_count;
+
+/* OBUF offsets from the beginning of the PCI resource address space. */
+extern const uint32_t szedata2_obuf_base_table[];
+extern const uint32_t szedata2_obuf_count;
+
+/**
+ * Macro takes pointer to pci resource structure (rsc)
+ * and returns pointer to mapped resource memory at
+ * specified offset (offset) typecast to the type (type).
+ */
+#define SZEDATA2_PCI_RESOURCE_PTR(rsc, offset, type) \
+	((type)(((uint8_t *)(rsc)->addr) + (offset)))
+
+/**
+ * Get pointer to IBUF structure according to specified index.
+ *
+ * @param rsc
+ *     Pointer to base address of memory resource.
+ * @param index
+ *     Index of IBUF.
+ * @return
+ *     Pointer to IBUF structure.
+ */
+static inline struct szedata2_ibuf *
+ibuf_ptr_by_index(struct rte_mem_resource *rsc, uint32_t index)
+{
+	if (index >= szedata2_ibuf_count)
+		index = szedata2_ibuf_count - 1;
+	return SZEDATA2_PCI_RESOURCE_PTR(rsc, szedata2_ibuf_base_table[index],
+		struct szedata2_ibuf *);
+}
+
+/**
+ * Get pointer to OBUF structure according to specified idnex.
+ *
+ * @param rsc
+ *     Pointer to base address of memory resource.
+ * @param index
+ *     Index of OBUF.
+ * @return
+ *     Pointer to OBUF structure.
+ */
+static inline struct szedata2_obuf *
+obuf_ptr_by_index(struct rte_mem_resource *rsc, uint32_t index)
+{
+	if (index >= szedata2_obuf_count)
+		index = szedata2_obuf_count - 1;
+	return SZEDATA2_PCI_RESOURCE_PTR(rsc, szedata2_obuf_base_table[index],
+		struct szedata2_obuf *);
+}
+
+#endif /* _SZEDATA2_IOBUF_H_ */