[dpdk-dev] [PATCH v4 08/14] raw/ifpga/base: store private features in FME and Port list

Rosen Xu rosen.xu at intel.com
Wed Apr 3 10:46:38 CEST 2019


From: "Zhang, Tianfei" <tianfei.zhang at intel.com>

Get private features attrubite like size, id, address after
enumeration, and insert into FEM or Port dedicate list.

when initial the private feature driver, we just compare the
private feature id between the list and feature drivers array
to match the proper drivers.

This patch avoid the hardcore in feature_info array in previous
implementation. and the same time we can use one driver for mulitple
devices which the id is the same.

Signed-off-by: Zhang, Tianfei <tianfei.zhang at intel.com>
---
 drivers/raw/ifpga_rawdev/base/ifpga_defines.h     |  46 ++-
 drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c   | 347 ++++++++--------------
 drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c | 160 +++++++---
 drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h |  46 ++-
 drivers/raw/ifpga_rawdev/base/ifpga_fme.c         |  32 ++
 drivers/raw/ifpga_rawdev/base/ifpga_hw.h          |  16 +-
 drivers/raw/ifpga_rawdev/base/ifpga_port.c        |  21 ++
 7 files changed, 363 insertions(+), 305 deletions(-)

diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_defines.h b/drivers/raw/ifpga_rawdev/base/ifpga_defines.h
index aa02527..217d0b1 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_defines.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_defines.h
@@ -15,6 +15,7 @@
 #define FME_FEATURE_GLOBAL_IPERF    "fme_iperf"
 #define FME_FEATURE_GLOBAL_ERR      "fme_error"
 #define FME_FEATURE_PR_MGMT         "fme_pr"
+#define FME_FEATURE_EMIF_MGMT       "fme_emif"
 #define FME_FEATURE_HSSI_ETH        "fme_hssi"
 #define FME_FEATURE_GLOBAL_DPERF    "fme_dperf"
 #define FME_FEATURE_QSPI_FLASH	    "fme_qspi_flash"
@@ -59,7 +60,8 @@
 #define FEATURE_FIU_ID_FME	0x0
 #define FEATURE_FIU_ID_PORT	0x1
 
-#define FEATURE_ID_HEADER	0x0
+/* Reserved 0xfe for Header, 0xff for AFU*/
+#define FEATURE_ID_FIU_HEADER	0xfe
 #define FEATURE_ID_AFU		0xff
 
 enum fpga_id_type {
@@ -68,31 +70,23 @@ enum fpga_id_type {
 	FPGA_ID_MAX,
 };
 
-enum fme_feature_id {
-	FME_FEATURE_ID_HEADER = 0x0,
-
-	FME_FEATURE_ID_THERMAL_MGMT	= 0x1,
-	FME_FEATURE_ID_POWER_MGMT = 0x2,
-	FME_FEATURE_ID_GLOBAL_IPERF = 0x3,
-	FME_FEATURE_ID_GLOBAL_ERR = 0x4,
-	FME_FEATURE_ID_PR_MGMT = 0x5,
-	FME_FEATURE_ID_HSSI_ETH = 0x6,
-	FME_FEATURE_ID_GLOBAL_DPERF = 0x7,
-	FME_FEATURE_ID_QSPI_FLASH = 0x8,
-
-	/* one for fme header. */
-	FME_FEATURE_ID_MAX = 0x9,
-};
-
-enum port_feature_id {
-	PORT_FEATURE_ID_HEADER = 0x0,
-	PORT_FEATURE_ID_ERROR = 0x1,
-	PORT_FEATURE_ID_UMSG = 0x2,
-	PORT_FEATURE_ID_UINT = 0x3,
-	PORT_FEATURE_ID_STP = 0x4,
-	PORT_FEATURE_ID_UAFU = 0x5,
-	PORT_FEATURE_ID_MAX = 0x6,
-};
+#define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
+#define FME_FEATURE_ID_THERMAL_MGMT 0x1
+#define FME_FEATURE_ID_POWER_MGMT 0x2
+#define FME_FEATURE_ID_GLOBAL_IPERF 0x3
+#define FME_FEATURE_ID_GLOBAL_ERR 0x4
+#define FME_FEATURE_ID_PR_MGMT 0x5
+#define FME_FEATURE_ID_HSSI_ETH 0x6
+#define FME_FEATURE_ID_GLOBAL_DPERF 0x7
+#define FME_FEATURE_ID_QSPI_FLASH 0x8
+#define FME_FEATURE_ID_EMIF_MGMT  0x9
+
+#define PORT_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
+#define PORT_FEATURE_ID_ERROR 0x10
+#define PORT_FEATURE_ID_UMSG 0x12
+#define PORT_FEATURE_ID_UINT 0x13
+#define PORT_FEATURE_ID_STP 0x14
+#define PORT_FEATURE_ID_UAFU FEATURE_ID_AFU
 
 /*
  * All headers and structures must be byte-packed to match the spec.
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c b/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c
index 848e518..c779e0c 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_enumerate.c
@@ -28,121 +28,24 @@ struct build_feature_devs_info {
 	struct ifpga_hw *hw;
 };
 
-struct feature_info {
-	const char *name;
-	u32 resource_size;
-	int feature_index;
-	int revision_id;
-	unsigned int vec_start;
-	unsigned int vec_cnt;
-
-	struct feature_ops *ops;
-};
+static int feature_revision(void __iomem *start)
+{
+	struct feature_header header;
 
-/* indexed by fme feature IDs which are defined in 'enum fme_feature_id'. */
-static struct feature_info fme_features[] = {
-	{
-		.name = FME_FEATURE_HEADER,
-		.resource_size = sizeof(struct feature_fme_header),
-		.feature_index = FME_FEATURE_ID_HEADER,
-		.revision_id = FME_HEADER_REVISION,
-		.ops = &fme_hdr_ops,
-	},
-	{
-		.name = FME_FEATURE_THERMAL_MGMT,
-		.resource_size = sizeof(struct feature_fme_thermal),
-		.feature_index = FME_FEATURE_ID_THERMAL_MGMT,
-		.revision_id = FME_THERMAL_MGMT_REVISION,
-		.ops = &fme_thermal_mgmt_ops,
-	},
-	{
-		.name = FME_FEATURE_POWER_MGMT,
-		.resource_size = sizeof(struct feature_fme_power),
-		.feature_index = FME_FEATURE_ID_POWER_MGMT,
-		.revision_id = FME_POWER_MGMT_REVISION,
-		.ops = &fme_power_mgmt_ops,
-	},
-	{
-		.name = FME_FEATURE_GLOBAL_IPERF,
-		.resource_size = sizeof(struct feature_fme_iperf),
-		.feature_index = FME_FEATURE_ID_GLOBAL_IPERF,
-		.revision_id = FME_GLOBAL_IPERF_REVISION,
-		.ops = &fme_global_iperf_ops,
-	},
-	{
-		.name = FME_FEATURE_GLOBAL_ERR,
-		.resource_size = sizeof(struct feature_fme_err),
-		.feature_index = FME_FEATURE_ID_GLOBAL_ERR,
-		.revision_id = FME_GLOBAL_ERR_REVISION,
-		.ops = &fme_global_err_ops,
-	},
-	{
-		.name = FME_FEATURE_PR_MGMT,
-		.resource_size = sizeof(struct feature_fme_pr),
-		.feature_index = FME_FEATURE_ID_PR_MGMT,
-		.revision_id = FME_PR_MGMT_REVISION,
-		.ops = &fme_pr_mgmt_ops,
-	},
-	{
-		.name = FME_FEATURE_HSSI_ETH,
-		.resource_size = sizeof(struct feature_fme_hssi),
-		.feature_index = FME_FEATURE_ID_HSSI_ETH,
-		.revision_id = FME_HSSI_ETH_REVISION
-	},
-	{
-		.name = FME_FEATURE_GLOBAL_DPERF,
-		.resource_size = sizeof(struct feature_fme_dperf),
-		.feature_index = FME_FEATURE_ID_GLOBAL_DPERF,
-		.revision_id = FME_GLOBAL_DPERF_REVISION,
-		.ops = &fme_global_dperf_ops,
-	}
-};
+	header.csr = readq(start);
 
-static struct feature_info port_features[] = {
-	{
-		.name = PORT_FEATURE_HEADER,
-		.resource_size = sizeof(struct feature_port_header),
-		.feature_index = PORT_FEATURE_ID_HEADER,
-		.revision_id = PORT_HEADER_REVISION,
-		.ops = &ifpga_rawdev_port_hdr_ops,
-	},
-	{
-		.name = PORT_FEATURE_ERR,
-		.resource_size = sizeof(struct feature_port_error),
-		.feature_index = PORT_FEATURE_ID_ERROR,
-		.revision_id = PORT_ERR_REVISION,
-		.ops = &ifpga_rawdev_port_error_ops,
-	},
-	{
-		.name = PORT_FEATURE_UMSG,
-		.resource_size = sizeof(struct feature_port_umsg),
-		.feature_index = PORT_FEATURE_ID_UMSG,
-		.revision_id = PORT_UMSG_REVISION,
-	},
-	{
-		.name = PORT_FEATURE_UINT,
-		.resource_size = sizeof(struct feature_port_uint),
-		.feature_index = PORT_FEATURE_ID_UINT,
-		.revision_id = PORT_UINT_REVISION,
-		.ops = &ifpga_rawdev_port_uint_ops,
-	},
-	{
-		.name = PORT_FEATURE_STP,
-		.resource_size = PORT_FEATURE_STP_REGION_SIZE,
-		.feature_index = PORT_FEATURE_ID_STP,
-		.revision_id = PORT_STP_REVISION,
-		.ops = &ifpga_rawdev_port_stp_ops,
-	},
-	{
-		.name = PORT_FEATURE_UAFU,
-		/* UAFU feature size should be read from PORT_CAP.MMIOSIZE.
-		 * Will set uafu feature size while parse port device.
-		 */
-		.resource_size = 0,
-		.feature_index = PORT_FEATURE_ID_UAFU,
-		.revision_id = PORT_UAFU_REVISION
-	},
-};
+	return header.revision;
+}
+
+static u32 feature_size(void __iomem *start)
+{
+	struct feature_header header;
+
+	header.csr = readq(start);
+
+	/*the size of private feature is 4KB aligned*/
+	return header.next_header_offset ? header.next_header_offset:4096;
+}
 
 static u64 feature_id(void __iomem *start)
 {
@@ -152,7 +55,7 @@ static u64 feature_id(void __iomem *start)
 
 	switch (header.type) {
 	case FEATURE_TYPE_FIU:
-		return FEATURE_ID_HEADER;
+		return FEATURE_ID_FIU_HEADER;
 	case FEATURE_TYPE_PRIVATE:
 		return header.id;
 	case FEATURE_TYPE_AFU:
@@ -165,37 +68,36 @@ static u64 feature_id(void __iomem *start)
 
 static int
 build_info_add_sub_feature(struct build_feature_devs_info *binfo,
-			   struct feature_info *finfo, void __iomem *start)
+		void __iomem *start, u64 fid, unsigned int size,
+		unsigned int vec_start,
+		unsigned int vec_cnt)
 {
 	struct ifpga_hw *hw = binfo->hw;
 	struct feature *feature = NULL;
-	int feature_idx = finfo->feature_index;
-	unsigned int vec_start = finfo->vec_start;
-	unsigned int vec_cnt = finfo->vec_cnt;
 	struct feature_irq_ctx *ctx = NULL;
 	int port_id, ret = 0;
 	unsigned int i;
 
-	if (binfo->current_type == FME_ID) {
-		feature = &hw->fme.sub_feature[feature_idx];
-		feature->parent = &hw->fme;
-	} else if (binfo->current_type == PORT_ID) {
-		port_id = binfo->current_port_id;
-		feature = &hw->port[port_id].sub_feature[feature_idx];
-		feature->parent = &hw->port[port_id];
-	} else {
-		return -EFAULT;
-	}
+	fid = fid?fid:feature_id(start);
+	size = size?size:feature_size(start);
+
+	feature = opae_malloc(sizeof(struct feature));
+	if (!feature)
+		return -ENOMEM;
 
 	feature->state = IFPGA_FEATURE_ATTACHED;
 	feature->addr = start;
-	feature->id = feature_id(start);
-	feature->size = finfo->resource_size;
-	feature->name = finfo->name;
-	feature->revision = finfo->revision_id;
-	feature->ops = finfo->ops;
+	feature->id = fid;
+	feature->size = size;
+	feature->revision = feature_revision(start);
 	feature->phys_addr = binfo->phys_addr +
 				((u8 *)start - (u8 *)binfo->ioaddr);
+	feature->vec_start = vec_start;
+	feature->vec_cnt = vec_cnt;
+
+	dev_debug(binfo, "%s: id=0x%llx, phys_addr=0x%llx, size=%u\n",
+			__func__, (unsigned long long)feature->id,
+			(unsigned long long)feature->phys_addr, size);
 
 	if (vec_cnt) {
 		if (vec_start + vec_cnt <= vec_start)
@@ -215,22 +117,32 @@ static u64 feature_id(void __iomem *start)
 	feature->ctx_num = vec_cnt;
 	feature->vfio_dev_fd = binfo->pci_data->vfio_dev_fd;
 
+	if (binfo->current_type == FME_ID) {
+		feature->parent = &hw->fme;
+		feature->type = FEATURE_FME_TYPE;
+		feature->name = get_fme_feature_name(fid);
+		TAILQ_INSERT_TAIL(&hw->fme.feature_list, feature, next);
+	} else if (binfo->current_type == PORT_ID) {
+		port_id = binfo->current_port_id;
+		feature->parent = &hw->port[port_id];
+		feature->type = FEATURE_PORT_TYPE;
+		feature->name = get_port_feature_name(fid);
+		TAILQ_INSERT_TAIL(&hw->port[port_id].feature_list,
+				feature, next);
+	} else {
+		return -EFAULT;
+	}
 	return ret;
 }
 
 static int
 create_feature_instance(struct build_feature_devs_info *binfo,
-			void __iomem *start, struct feature_info *finfo)
+			void __iomem *start, u64 fid,
+			unsigned int size, unsigned int vec_start,
+			unsigned int vec_cnt)
 {
-	struct feature_header *hdr = start;
-
-	if (finfo->revision_id != SKIP_REVISION_CHECK &&
-	    hdr->revision > finfo->revision_id) {
-		dev_err(binfo, "feature %s revision :default:%x, now at:%x, mis-match.\n",
-			finfo->name, finfo->revision_id, hdr->revision);
-	}
-
-	return build_info_add_sub_feature(binfo, finfo, start);
+	return build_info_add_sub_feature(binfo, start, fid, size, vec_start,
+			vec_cnt);
 }
 
 /*
@@ -249,31 +161,30 @@ static bool feature_is_UAFU(struct build_feature_devs_info *binfo)
 static int parse_feature_port_uafu(struct build_feature_devs_info *binfo,
 				   struct feature_header *hdr)
 {
-	enum port_feature_id id = PORT_FEATURE_ID_UAFU;
+	u64 id = PORT_FEATURE_ID_UAFU;
 	struct ifpga_afu_info *info;
 	void *start = (void *)hdr;
+	struct feature_port_header *port_hdr = binfo->ioaddr;
+	struct feature_port_capability capability;
 	int ret;
+	int size;
 
-	if (port_features[id].resource_size) {
-		ret = create_feature_instance(binfo, hdr, &port_features[id]);
-	} else {
-		dev_err(binfo, "the uafu feature header is mis-configured.\n");
-		ret = -EINVAL;
-	}
+	capability.csr = readq(&port_hdr->capability);
+
+	size = capability.mmio_size << 10;
 
+	ret = create_feature_instance(binfo, hdr, id, size, 0, 0);
 	if (ret)
 		return ret;
 
-	/* FIXME: need to figure out a better name */
-	info = malloc(sizeof(*info));
+	info = opae_malloc(sizeof(*info));
 	if (!info)
 		return -ENOMEM;
 
 	info->region[0].addr = start;
 	info->region[0].phys_addr = binfo->phys_addr +
 			(uint8_t *)start - (uint8_t *)binfo->ioaddr;
-	info->region[0].len = port_features[id].resource_size;
-	port_features[id].resource_size = 0;
+	info->region[0].len = size;
 	info->num_regions = 1;
 
 	binfo->acc_info = info;
@@ -320,6 +231,8 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
 	struct opae_manager *mgr;
 	struct opae_bridge *br;
 	struct opae_accelerator *acc;
+	struct ifpga_port_hw *port;
+	struct feature *feature;
 
 	if (!binfo->fiu)
 		return 0;
@@ -337,7 +250,11 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
 		br->id = binfo->current_port_id;
 
 		/* update irq info */
-		info->num_irqs = port_features[PORT_FEATURE_ID_UINT].vec_cnt;
+		port = &hw->port[binfo->current_port_id];
+		feature = get_feature_by_id(&port->feature_list,
+				PORT_FEATURE_ID_UINT);
+		if (feature)
+			info->num_irqs = feature->vec_cnt;
 
 		acc = opae_accelerator_alloc(hw->adapter->name,
 					     &ifpga_acc_ops, info);
@@ -353,7 +270,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
 
 	} else if (binfo->current_type == FME_ID) {
 		mgr = opae_manager_alloc(hw->adapter->name, &ifpga_mgr_ops,
-					 binfo->fiu);
+				binfo->fiu);
 		if (!mgr)
 			return -ENOMEM;
 
@@ -402,10 +319,10 @@ static int parse_feature_fme(struct build_feature_devs_info *binfo,
 	/* Update FME states */
 	fme->state = IFPGA_FME_IMPLEMENTED;
 	fme->parent = hw;
+	TAILQ_INIT(&fme->feature_list);
 	spinlock_init(&fme->lock);
 
-	return create_feature_instance(binfo, start,
-				       &fme_features[FME_FEATURE_ID_HEADER]);
+	return create_feature_instance(binfo, start, 0, 0, 0, 0);
 }
 
 static int parse_feature_port(struct build_feature_devs_info *binfo,
@@ -433,29 +350,19 @@ static int parse_feature_port(struct build_feature_devs_info *binfo,
 	port->parent = hw;
 	port->state = IFPGA_PORT_ATTACHED;
 	spinlock_init(&port->lock);
+	TAILQ_INIT(&port->feature_list);
 
-	return create_feature_instance(binfo, start,
-				      &port_features[PORT_FEATURE_ID_HEADER]);
+	return create_feature_instance(binfo, start, 0, 0, 0, 0);
 }
 
 static void enable_port_uafu(struct build_feature_devs_info *binfo,
 			     void __iomem *start)
 {
-	enum port_feature_id id = PORT_FEATURE_ID_UAFU;
-	struct feature_port_header *port_hdr;
-	struct feature_port_capability capability;
 	struct ifpga_port_hw *port = &binfo->hw->port[binfo->current_port_id];
 
-	port_hdr = (struct feature_port_header *)start;
-	capability.csr = readq(&port_hdr->capability);
-	port_features[id].resource_size = (capability.mmio_size << 10);
-
-	/*
-	 * From spec, to Enable UAFU, we should reset related port,
-	 * or the whole mmio space in this UAFU will be invalid
-	 */
-	if (port_features[id].resource_size)
-		fpga_port_reset(port);
+	UNUSED(start);
+
+	fpga_port_reset(port);
 }
 
 static int parse_feature_fiu(struct build_feature_devs_info *binfo,
@@ -505,44 +412,45 @@ static int parse_feature_fiu(struct build_feature_devs_info *binfo,
 }
 
 static void parse_feature_irqs(struct build_feature_devs_info *binfo,
-			       void __iomem *start, struct feature_info *finfo)
+		void __iomem *start, unsigned int *vec_start,
+		unsigned int *vec_cnt)
 {
-	finfo->vec_start = 0;
-	finfo->vec_cnt = 0;
-
 	UNUSED(binfo);
+	u64 id;
+
+	id = feature_id(start);
 
-	if (!strcmp(finfo->name, PORT_FEATURE_UINT)) {
+	if (id == PORT_FEATURE_ID_UINT) {
 		struct feature_port_uint *port_uint = start;
 		struct feature_port_uint_cap uint_cap;
 
 		uint_cap.csr = readq(&port_uint->capability);
 		if (uint_cap.intr_num) {
-			finfo->vec_start = uint_cap.first_vec_num;
-			finfo->vec_cnt = uint_cap.intr_num;
+			*vec_start = uint_cap.first_vec_num;
+			*vec_cnt = uint_cap.intr_num;
 		} else {
 			dev_debug(binfo, "UAFU doesn't support interrupt\n");
 		}
-	} else if (!strcmp(finfo->name, PORT_FEATURE_ERR)) {
+	} else if (id == PORT_FEATURE_ID_ERROR) {
 		struct feature_port_error *port_err = start;
 		struct feature_port_err_capability port_err_cap;
 
 		port_err_cap.csr = readq(&port_err->error_capability);
 		if (port_err_cap.support_intr) {
-			finfo->vec_start = port_err_cap.intr_vector_num;
-			finfo->vec_cnt = 1;
+			*vec_start = port_err_cap.intr_vector_num;
+			*vec_cnt = 1;
 		} else {
 			dev_debug(&binfo, "Port error doesn't support interrupt\n");
 		}
 
-	} else if (!strcmp(finfo->name, FME_FEATURE_GLOBAL_ERR)) {
+	} else if (id == FME_FEATURE_ID_GLOBAL_ERR) {
 		struct feature_fme_err *fme_err = start;
 		struct feature_fme_error_capability fme_err_cap;
 
 		fme_err_cap.csr = readq(&fme_err->fme_err_capability);
 		if (fme_err_cap.support_intr) {
-			finfo->vec_start = fme_err_cap.intr_vector_num;
-			finfo->vec_cnt = 1;
+			*vec_start = fme_err_cap.intr_vector_num;
+			*vec_cnt = 1;
 		} else {
 			dev_debug(&binfo, "FME error doesn't support interrupt\n");
 		}
@@ -552,43 +460,23 @@ static void parse_feature_irqs(struct build_feature_devs_info *binfo,
 static int parse_feature_fme_private(struct build_feature_devs_info *binfo,
 				     struct feature_header *hdr)
 {
-	struct feature_header header;
-
-	header.csr = readq(hdr);
-
-	if (header.id >= ARRAY_SIZE(fme_features)) {
-		dev_err(binfo, "FME feature id %x is not supported yet.\n",
-			header.id);
-		return 0;
-	}
+	unsigned int vec_start = 0;
+	unsigned int vec_cnt = 0;
 
-	parse_feature_irqs(binfo, hdr, &fme_features[header.id]);
+	parse_feature_irqs(binfo, hdr, &vec_start, &vec_cnt);
 
-	return create_feature_instance(binfo, hdr, &fme_features[header.id]);
+	return create_feature_instance(binfo, hdr, 0, 0, vec_start, vec_cnt);
 }
 
 static int parse_feature_port_private(struct build_feature_devs_info *binfo,
 				      struct feature_header *hdr)
 {
-	struct feature_header header;
-	enum port_feature_id id;
+	unsigned int vec_start = 0;
+	unsigned int vec_cnt = 0;
 
-	header.csr = readq(hdr);
-	/*
-	 * the region of port feature id is [0x10, 0x13], + 1 to reserve 0
-	 * which is dedicated for port-hdr.
-	 */
-	id = (header.id & 0x000f) + 1;
-
-	if (id >= ARRAY_SIZE(port_features)) {
-		dev_err(binfo, "Port feature id %x is not supported yet.\n",
-			header.id);
-		return 0;
-	}
-
-	parse_feature_irqs(binfo, hdr, &port_features[id]);
+	parse_feature_irqs(binfo, hdr, &vec_start, &vec_cnt);
 
-	return create_feature_instance(binfo, hdr, &port_features[id]);
+	return create_feature_instance(binfo, hdr, 0, 0, vec_start, vec_cnt);
 }
 
 static int parse_feature_private(struct build_feature_devs_info *binfo,
@@ -651,12 +539,18 @@ static int parse_feature(struct build_feature_devs_info *binfo,
 		}
 
 		hdr = (struct feature_header *)start;
+		header.csr = readq(hdr);
+
+		dev_debug(binfo, "%s: address=0x%p, val=0x%llx, header.id=0x%x, header.next_offset=0x%x, header.eol=0x%x, header.type=0x%x\n",
+			__func__, hdr, (unsigned long long)header.csr,
+			header.id, header.next_header_offset,
+			header.end_of_list, header.type);
+
 		ret = parse_feature(binfo, hdr);
 		if (ret)
 			return ret;
 
-		header.csr = readq(hdr);
-		if (!header.next_header_offset)
+		if (header.end_of_list || !header.next_header_offset)
 			break;
 	}
 
@@ -746,20 +640,20 @@ static void ifpga_print_device_feature_list(struct ifpga_hw *hw)
 	struct ifpga_fme_hw *fme = &hw->fme;
 	struct ifpga_port_hw *port;
 	struct feature *feature;
-	int i, j;
+	int i;
 
 	dev_info(hw, "found fme_device, is in PF: %s\n",
 		 is_ifpga_hw_pf(hw) ? "yes" : "no");
 
-	for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
-		feature = &fme->sub_feature[i];
+	ifpga_for_each_fme_feature(fme, feature) {
 		if (feature->state != IFPGA_FEATURE_ATTACHED)
 			continue;
 
-		dev_info(hw, "%12s:	0x%p - 0x%p  - paddr: 0x%lx\n",
+		dev_info(hw, "%12s:	%p - %p  - paddr: 0x%lx\n",
 			 feature->name, feature->addr,
 			 feature->addr + feature->size - 1,
 			 (unsigned long)feature->phys_addr);
+
 	}
 
 	for (i = 0; i < MAX_FPGA_PORT_NUM; i++) {
@@ -770,18 +664,18 @@ static void ifpga_print_device_feature_list(struct ifpga_hw *hw)
 
 		dev_info(hw, "port device: %d\n", port->port_id);
 
-		for (j = 0; j < PORT_FEATURE_ID_MAX; j++) {
-			feature = &port->sub_feature[j];
+		ifpga_for_each_port_feature(port, feature) {
 			if (feature->state != IFPGA_FEATURE_ATTACHED)
 				continue;
 
-			dev_info(hw, "%12s:	0x%p - 0x%p  - paddr:0x%lx\n",
+			dev_info(hw, "%12s:	%p - %p  - paddr:0x%lx\n",
 				 feature->name,
 				 feature->addr,
 				 feature->addr +
 				 feature->size - 1,
 				 (unsigned long)feature->phys_addr);
 		}
+
 	}
 }
 
@@ -812,10 +706,13 @@ int ifpga_bus_enumerate(struct ifpga_hw *hw)
 int ifpga_bus_init(struct ifpga_hw *hw)
 {
 	int i;
+	struct ifpga_port_hw *port;
 
 	fme_hw_init(&hw->fme);
-	for (i = 0; i < MAX_FPGA_PORT_NUM; i++)
-		port_hw_init(&hw->port[i]);
+	for (i = 0; i < MAX_FPGA_PORT_NUM; i++) {
+		port = &hw->port[i];
+		port_hw_init(port);
+	}
 
 	return 0;
 }
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
index 0a27c38..d82a890 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.c
@@ -70,6 +70,9 @@ int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid)
 	struct feature_port_header *port_hdr;
 	u64 guidl, guidh;
 
+	if (!uuid)
+		return -EINVAL;
+
 	port_hdr = get_port_feature_ioaddr_by_index(port, PORT_FEATURE_ID_UAFU);
 
 	spinlock_lock(&port->lock);
@@ -177,77 +180,146 @@ int port_clear_error(struct ifpga_port_hw *port)
 	return port_err_clear(port, error.csr);
 }
 
-void fme_hw_uinit(struct ifpga_fme_hw *fme)
+static struct feature_driver fme_feature_drvs[] = {
+	{FEATURE_DRV(FME_FEATURE_ID_HEADER, FME_FEATURE_HEADER,
+			&fme_hdr_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_THERMAL_MGMT, FME_FEATURE_THERMAL_MGMT,
+			&fme_thermal_mgmt_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_POWER_MGMT, FME_FEATURE_POWER_MGMT,
+			&fme_power_mgmt_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_GLOBAL_ERR, FME_FEATURE_GLOBAL_ERR,
+			&fme_global_err_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_PR_MGMT, FME_FEATURE_PR_MGMT,
+			&fme_pr_mgmt_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_GLOBAL_DPERF, FME_FEATURE_GLOBAL_DPERF,
+			&fme_global_dperf_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_HSSI_ETH, FME_FEATURE_HSSI_ETH,
+	&fme_hssi_eth_ops),},
+	{FEATURE_DRV(FME_FEATURE_ID_EMIF_MGMT, FME_FEATURE_EMIF_MGMT,
+	&fme_emif_ops),},
+	{0, NULL, NULL}, /* end of arrary */
+};
+
+static struct feature_driver port_feature_drvs[] = {
+	{FEATURE_DRV(PORT_FEATURE_ID_HEADER, PORT_FEATURE_HEADER,
+			&ifpga_rawdev_port_hdr_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_ERROR, PORT_FEATURE_ERR,
+			&ifpga_rawdev_port_error_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_UINT, PORT_FEATURE_UINT,
+			&ifpga_rawdev_port_uint_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_STP, PORT_FEATURE_STP,
+			&ifpga_rawdev_port_stp_ops)},
+	{FEATURE_DRV(PORT_FEATURE_ID_UAFU, PORT_FEATURE_UAFU,
+			&ifpga_rawdev_port_afu_ops)},
+	{0, NULL, NULL}, /* end of array */
+};
+
+const char *get_fme_feature_name(unsigned int id)
 {
-	struct feature *feature;
-	int i;
+	struct feature_driver *drv = fme_feature_drvs;
 
-	if (fme->state != IFPGA_FME_IMPLEMENTED)
-		return;
+	while (drv->name) {
+		if (drv->id == id)
+			return drv->name;
 
-	for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
-		feature = &fme->sub_feature[i];
-		if (feature->state == IFPGA_FEATURE_ATTACHED &&
-		    feature->ops && feature->ops->uinit)
-			feature->ops->uinit(feature);
+		drv++;
 	}
+
+	return NULL;
 }
 
-int fme_hw_init(struct ifpga_fme_hw *fme)
+const char *get_port_feature_name(unsigned int id)
+{
+	struct feature_driver *drv = port_feature_drvs;
+
+	while (drv->name) {
+		if (drv->id == id)
+			return drv->name;
+
+		drv++;
+	}
+
+	return NULL;
+}
+
+static void feature_uinit(struct ifpga_feature_list *list)
 {
 	struct feature *feature;
-	int i, ret;
 
-	if (fme->state != IFPGA_FME_IMPLEMENTED)
-		return -EINVAL;
+	TAILQ_FOREACH(feature, list, next) {
+		if (feature->state != IFPGA_FEATURE_ATTACHED)
+			continue;
+		if (feature->ops && feature->ops->uinit)
+			feature->ops->uinit(feature);
+	}
+}
 
-	for (i = 0; i < FME_FEATURE_ID_MAX; i++) {
-		feature = &fme->sub_feature[i];
-		if (feature->state == IFPGA_FEATURE_ATTACHED &&
-		    feature->ops && feature->ops->init) {
-			ret = feature->ops->init(feature);
-			if (ret) {
-				fme_hw_uinit(fme);
-				return ret;
+static int feature_init(struct feature_driver *drv,
+		struct ifpga_feature_list *list)
+{
+	struct feature *feature;
+	int ret;
+
+	while (drv->ops) {
+		TAILQ_FOREACH(feature, list, next) {
+			if (feature->state != IFPGA_FEATURE_ATTACHED)
+				continue;
+			if (feature->id == drv->id) {
+				feature->ops = drv->ops;
+				feature->name = drv->name;
+				if (feature->ops->init) {
+					ret = feature->ops->init(feature);
+					if (ret)
+						goto error;
+				}
 			}
 		}
+		drv++;
 	}
 
 	return 0;
+error:
+	feature_uinit(list);
+	return ret;
 }
 
-void port_hw_uinit(struct ifpga_port_hw *port)
+int fme_hw_init(struct ifpga_fme_hw *fme)
 {
-	struct feature *feature;
-	int i;
+	int ret;
 
-	for (i = 0; i < PORT_FEATURE_ID_MAX; i++) {
-		feature = &port->sub_feature[i];
-		if (feature->state == IFPGA_FEATURE_ATTACHED &&
-		    feature->ops && feature->ops->uinit)
-			feature->ops->uinit(feature);
-	}
+	if (fme->state != IFPGA_FME_IMPLEMENTED)
+		return -ENODEV;
+
+	ret = feature_init(fme_feature_drvs, &fme->feature_list);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+void fme_hw_uinit(struct ifpga_fme_hw *fme)
+{
+	feature_uinit(&fme->feature_list);
+}
+
+void port_hw_uinit(struct ifpga_port_hw *port)
+{
+	feature_uinit(&port->feature_list);
 }
 
 int port_hw_init(struct ifpga_port_hw *port)
 {
-	struct feature *feature;
-	int i, ret;
+	int ret;
 
 	if (port->state == IFPGA_PORT_UNUSED)
 		return 0;
 
-	for (i = 0; i < PORT_FEATURE_ID_MAX; i++) {
-		feature = &port->sub_feature[i];
-		if (feature->ops && feature->ops->init) {
-			ret = feature->ops->init(feature);
-			if (ret) {
-				port_hw_uinit(port);
-				return ret;
-			}
-		}
-	}
+	ret = feature_init(port_feature_drvs, &port->feature_list);
+	if (ret)
+		goto error;
 
 	return 0;
+error:
+	port_hw_uinit(port);
+	return ret;
 }
-
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h
index 4391f2f..1d80f1d 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_feature_dev.h
@@ -7,6 +7,18 @@
 
 #include "ifpga_hw.h"
 
+struct feature_driver {
+	u64 id;
+	const char *name;
+	struct feature_ops *ops;
+};
+
+/**
+ * FEATURE_DRV - macro used to describe a specific feature driver
+ */
+#define FEATURE_DRV(n, s, p) \
+	.id = (n), .name = (s), .ops = (p)
+
 static inline struct ifpga_port_hw *
 get_port(struct ifpga_hw *hw, u32 port_id)
 {
@@ -17,12 +29,10 @@
 }
 
 #define ifpga_for_each_fme_feature(hw, feature)		\
-	for ((feature) = (hw)->sub_feature;			\
-	   (feature) < (hw)->sub_feature + (FME_FEATURE_ID_MAX); (feature)++)
+	TAILQ_FOREACH(feature, &hw->feature_list, next)
 
-#define ifpga_for_each_port_feature(hw, feature)		\
-	for ((feature) = (hw)->sub_feature;			\
-	   (feature) < (hw)->sub_feature + (PORT_FEATURE_ID_MAX); (feature)++)
+#define ifpga_for_each_port_feature(port, feature)		\
+	TAILQ_FOREACH(feature, &port->feature_list, next)
 
 static inline struct feature *
 get_fme_feature_by_id(struct ifpga_fme_hw *fme, u64 id)
@@ -50,16 +60,32 @@
 	return NULL;
 }
 
+static inline struct feature *
+get_feature_by_id(struct ifpga_feature_list *list, u64 id)
+{
+	struct feature *feature;
+
+	TAILQ_FOREACH(feature, list, next)
+		if (feature->id == id)
+			return feature;
+
+	return NULL;
+}
+
 static inline void  *
 get_fme_feature_ioaddr_by_index(struct ifpga_fme_hw *fme, int index)
 {
-	return fme->sub_feature[index].addr;
+	struct feature *feature = get_feature_by_id(&fme->feature_list, index);
+
+	return feature ? feature->addr : NULL;
 }
 
 static inline void  *
 get_port_feature_ioaddr_by_index(struct ifpga_port_hw *port, int index)
 {
-	return port->sub_feature[index].addr;
+	struct feature *feature = get_feature_by_id(&port->feature_list, index);
+
+	return feature ? feature->addr : NULL;
 }
 
 static inline bool
@@ -143,6 +169,8 @@ int do_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size,
 extern struct feature_ops fme_pr_mgmt_ops;
 extern struct feature_ops fme_global_iperf_ops;
 extern struct feature_ops fme_global_dperf_ops;
+extern struct feature_ops fme_hssi_eth_ops;
+extern struct feature_ops fme_emif_ops;
 
 int port_get_prop(struct ifpga_port_hw *port, struct feature_prop *prop);
 int port_set_prop(struct ifpga_port_hw *port, struct feature_prop *prop);
@@ -155,14 +183,16 @@ struct fpga_uafu_irq_set {
 };
 
 int port_set_irq(struct ifpga_port_hw *port, u32 feature_id, void *irq_set);
+const char *get_fme_feature_name(unsigned int id);
+const char *get_port_feature_name(unsigned int id);
 
 extern struct feature_ops ifpga_rawdev_port_hdr_ops;
 extern struct feature_ops ifpga_rawdev_port_error_ops;
 extern struct feature_ops ifpga_rawdev_port_stp_ops;
 extern struct feature_ops ifpga_rawdev_port_uint_ops;
+extern struct feature_ops ifpga_rawdev_port_afu_ops;
 
 /* help functions for feature ops */
 int fpga_msix_set_block(struct feature *feature, unsigned int start,
 			unsigned int count, s32 *fds);
-
 #endif /* _IFPGA_FEATURE_DEV_H_ */
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_fme.c b/drivers/raw/ifpga_rawdev/base/ifpga_fme.c
index 4be60c0..9451086 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_fme.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_fme.c
@@ -732,3 +732,35 @@ struct feature_ops fme_power_mgmt_ops = {
 	.get_prop = fme_power_mgmt_get_prop,
 	.set_prop = fme_power_mgmt_set_prop,
 };
+
+static int fme_hssi_eth_init(struct feature *feature)
+{
+	UNUSED(feature);
+	return 0;
+}
+
+static void fme_hssi_eth_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+}
+
+struct feature_ops fme_hssi_eth_ops = {
+	.init = fme_hssi_eth_init,
+	.uinit = fme_hssi_eth_uinit,
+};
+
+static int fme_emif_init(struct feature *feature)
+{
+	UNUSED(feature);
+	return 0;
+}
+
+static void fme_emif_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+}
+
+struct feature_ops fme_emif_ops = {
+	.init = fme_emif_init,
+	.uinit = fme_emif_uinit,
+};
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_hw.h b/drivers/raw/ifpga_rawdev/base/ifpga_hw.h
index a20520c..8aaa056 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_hw.h
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_hw.h
@@ -8,18 +8,28 @@
 #include "ifpga_defines.h"
 #include "opae_ifpga_hw_api.h"
 
+/** List of private feateues */
+TAILQ_HEAD(ifpga_feature_list, feature);
+
 enum ifpga_feature_state {
 	IFPGA_FEATURE_UNUSED = 0,
 	IFPGA_FEATURE_ATTACHED,
 };
 
+enum feature_type {
+	FEATURE_FME_TYPE = 0,
+	FEATURE_PORT_TYPE,
+};
+
 struct feature_irq_ctx {
 	int eventfd;
 	int idx;
 };
 
 struct feature {
+	TAILQ_ENTRY(feature)next;
 	enum ifpga_feature_state state;
+	enum feature_type type;
 	const char *name;
 	u64 id;
 	u8 *addr;
@@ -34,6 +44,8 @@ struct feature {
 	void *parent;		/* to parent hw data structure */
 
 	struct feature_ops *ops;/* callback to this private feature */
+	unsigned int vec_start;
+	unsigned int vec_cnt;
 };
 
 struct feature_ops {
@@ -52,7 +64,7 @@ enum ifpga_fme_state {
 struct ifpga_fme_hw {
 	enum ifpga_fme_state state;
 
-	struct feature sub_feature[FME_FEATURE_ID_MAX];
+	struct ifpga_feature_list feature_list;
 	spinlock_t lock;	/* protect hardware access */
 
 	void *parent;		/* pointer to ifpga_hw */
@@ -78,7 +90,7 @@ enum ifpga_port_state {
 struct ifpga_port_hw {
 	enum ifpga_port_state state;
 
-	struct feature sub_feature[PORT_FEATURE_ID_MAX];
+	struct ifpga_feature_list feature_list;
 	spinlock_t lock;	/* protect access to hw */
 
 	void *parent;		/* pointer to ifpga_hw */
diff --git a/drivers/raw/ifpga_rawdev/base/ifpga_port.c b/drivers/raw/ifpga_rawdev/base/ifpga_port.c
index 8b5668d..4628783 100644
--- a/drivers/raw/ifpga_rawdev/base/ifpga_port.c
+++ b/drivers/raw/ifpga_rawdev/base/ifpga_port.c
@@ -386,3 +386,24 @@ struct feature_ops ifpga_rawdev_port_uint_ops = {
 	.init = port_uint_init,
 	.uinit = port_uint_uinit,
 };
+
+static int port_afu_init(struct feature *feature)
+{
+	UNUSED(feature);
+
+	dev_info(NULL, "PORT AFU Init.\n");
+
+	return 0;
+}
+
+static void port_afu_uinit(struct feature *feature)
+{
+	UNUSED(feature);
+
+	dev_info(NULL, "PORT AFU UInit.\n");
+}
+
+struct feature_ops ifpga_rawdev_port_afu_ops = {
+	.init = port_afu_init,
+	.uinit = port_afu_uinit,
+};
-- 
1.8.3.1



More information about the dev mailing list