From e4dc499d565b6597dde7b4d81d64f0466a3feb72 Mon Sep 17 00:00:00 2001 From: Tianfei Zhang Date: Tue, 16 Apr 2019 11:17:45 +0800 Subject: [PATCH] raw/ifpga/base: store private features in FME and port Get private features attribute 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: Tianfei Zhang --- drivers/raw/ifpga_rawdev/base/ifpga_defines.h | 46 +-- .../raw/ifpga_rawdev/base/ifpga_enumerate.c | 347 ++++++------------ .../raw/ifpga_rawdev/base/ifpga_feature_dev.c | 160 +++++--- .../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 aa02527208..217d0b1617 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 848e5183ad..c779e0c0e7 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 @@ build_info_add_sub_feature(struct build_feature_devs_info *binfo, 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 @@ parse_feature_list(struct build_feature_devs_info *binfo, u8 __iomem *start) } 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 @@ exit: 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 0a27c38588..d82a8906f3 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 4391f2fdf9..1d80f1d1ef 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 @@ get_port(struct ifpga_hw *hw, u32 port_id) } #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 @@ get_port_feature_by_id(struct ifpga_port_hw *port, u64 id) 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 @@ extern struct feature_ops fme_global_err_ops; 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 4be60c0c1c..9451086aa1 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 a20520c960..8aaa056fdf 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 8b5668d49a..462878339c 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, +}; -- 2.20.1