Sorry, cover-letter has been lost for some unknown problem. I will resend the patch set. On 2017/11/14 17:26, Yixian Liu wrote: > Considering the compatibility of supporting hip08's eq > process and possible changes of data structure, this patch > refactors the eq code structure of hip06. > > We move all the eq process code for hip06 from hns_roce_eq.c > into hns_roce_hw_v1.c, and also for hns_roce_eq.h. With > these changes, it will be convenient to add the eq support > for later hardware version. > > Signed-off-by: Yixian Liu <liuyixian@xxxxxxxxxx> > Reviewed-by: Lijun Ou <oulijun@xxxxxxxxxx> > Reviewed-by: Wei Hu (Xavier) <xavier.huwei@xxxxxxxxxx> > --- > drivers/infiniband/hw/hns/Makefile | 2 +- > drivers/infiniband/hw/hns/hns_roce_cmd.c | 1 + > drivers/infiniband/hw/hns/hns_roce_cq.c | 19 +- > drivers/infiniband/hw/hns/hns_roce_device.h | 57 ++- > drivers/infiniband/hw/hns/hns_roce_eq.c | 759 ---------------------------- > drivers/infiniband/hw/hns/hns_roce_eq.h | 134 ----- > drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 740 ++++++++++++++++++++++++++- > drivers/infiniband/hw/hns/hns_roce_hw_v1.h | 44 +- > drivers/infiniband/hw/hns/hns_roce_main.c | 16 +- > drivers/infiniband/hw/hns/hns_roce_qp.c | 1 + > 10 files changed, 843 insertions(+), 930 deletions(-) > delete mode 100644 drivers/infiniband/hw/hns/hns_roce_eq.c > delete mode 100644 drivers/infiniband/hw/hns/hns_roce_eq.h > > diff --git a/drivers/infiniband/hw/hns/Makefile b/drivers/infiniband/hw/hns/Makefile > index ff426a6..97bf2cd 100644 > --- a/drivers/infiniband/hw/hns/Makefile > +++ b/drivers/infiniband/hw/hns/Makefile > @@ -5,7 +5,7 @@ > ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3 > > obj-$(CONFIG_INFINIBAND_HNS) += hns-roce.o > -hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_eq.o hns_roce_pd.o \ > +hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \ > hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \ > hns_roce_cq.o hns_roce_alloc.o > obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o > diff --git a/drivers/infiniband/hw/hns/hns_roce_cmd.c b/drivers/infiniband/hw/hns/hns_roce_cmd.c > index 1085cb2..9ebe839 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_cmd.c > +++ b/drivers/infiniband/hw/hns/hns_roce_cmd.c > @@ -103,6 +103,7 @@ void hns_roce_cmd_event(struct hns_roce_dev *hr_dev, u16 token, u8 status, > context->out_param = out_param; > complete(&context->done); > } > +EXPORT_SYMBOL_GPL(hns_roce_cmd_event); > > /* this should be called with "use_events" */ > static int __hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev, u64 in_param, > diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c > index 2111b57..bccc9b5 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_cq.c > +++ b/drivers/infiniband/hw/hns/hns_roce_cq.c > @@ -196,15 +196,14 @@ void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) > if (ret) > dev_err(dev, "HW2SW_CQ failed (%d) for CQN %06lx\n", ret, > hr_cq->cqn); > - if (hr_dev->eq_table.eq) { > - /* Waiting interrupt process procedure carried out */ > - synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq); > - > - /* wait for all interrupt processed */ > - if (atomic_dec_and_test(&hr_cq->refcount)) > - complete(&hr_cq->free); > - wait_for_completion(&hr_cq->free); > - } > + > + /* Waiting interrupt process procedure carried out */ > + synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq); > + > + /* wait for all interrupt processed */ > + if (atomic_dec_and_test(&hr_cq->refcount)) > + complete(&hr_cq->free); > + wait_for_completion(&hr_cq->free); > > spin_lock_irq(&cq_table->lock); > radix_tree_delete(&cq_table->tree, hr_cq->cqn); > @@ -460,6 +459,7 @@ void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn) > ++cq->arm_sn; > cq->comp(cq); > } > +EXPORT_SYMBOL_GPL(hns_roce_cq_completion); > > void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type) > { > @@ -482,6 +482,7 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type) > if (atomic_dec_and_test(&cq->refcount)) > complete(&cq->free); > } > +EXPORT_SYMBOL_GPL(hns_roce_cq_event); > > int hns_roce_init_cq_table(struct hns_roce_dev *hr_dev) > { > diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h > index 01d3d69..9aa9e94 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_device.h > +++ b/drivers/infiniband/hw/hns/hns_roce_device.h > @@ -62,12 +62,16 @@ > #define HNS_ROCE_CQE_WCMD_EMPTY_BIT 0x2 > #define HNS_ROCE_MIN_CQE_CNT 16 > > -#define HNS_ROCE_MAX_IRQ_NUM 34 > +#define HNS_ROCE_MAX_IRQ_NUM 128 > > -#define HNS_ROCE_COMP_VEC_NUM 32 > +#define EQ_ENABLE 1 > +#define EQ_DISABLE 0 > > -#define HNS_ROCE_AEQE_VEC_NUM 1 > -#define HNS_ROCE_AEQE_OF_VEC_NUM 1 > +#define HNS_ROCE_CEQ 0 > +#define HNS_ROCE_AEQ 1 > + > +#define HNS_ROCE_CEQ_ENTRY_SIZE 0x4 > +#define HNS_ROCE_AEQ_ENTRY_SIZE 0x10 > > /* 4G/4K = 1M */ > #define HNS_ROCE_SL_SHIFT 28 > @@ -485,6 +489,45 @@ struct hns_roce_ib_iboe { > u8 phy_port[HNS_ROCE_MAX_PORTS]; > }; > > +enum { > + HNS_ROCE_EQ_STAT_INVALID = 0, > + HNS_ROCE_EQ_STAT_VALID = 2, > +}; > + > +struct hns_roce_ceqe { > + u32 comp; > +}; > + > +struct hns_roce_aeqe { > + u32 asyn; > + union { > + struct { > + u32 qp; > + u32 rsv0; > + u32 rsv1; > + } qp_event; > + > + struct { > + u32 cq; > + u32 rsv0; > + u32 rsv1; > + } cq_event; > + > + struct { > + u32 ceqe; > + u32 rsv0; > + u32 rsv1; > + } ce_event; > + > + struct { > + __le64 out_param; > + __le16 token; > + u8 status; > + u8 rsv0; > + } __packed cmd; > + } event; > +}; > + > struct hns_roce_eq { > struct hns_roce_dev *hr_dev; > void __iomem *doorbell; > @@ -502,7 +545,7 @@ struct hns_roce_eq { > > struct hns_roce_eq_table { > struct hns_roce_eq *eq; > - void __iomem **eqc_base; > + void __iomem **eqc_base; /* only for hw v1 */ > }; > > struct hns_roce_caps { > @@ -550,7 +593,7 @@ struct hns_roce_caps { > u32 pbl_buf_pg_sz; > u32 pbl_hop_num; > int aeqe_depth; > - int ceqe_depth[HNS_ROCE_COMP_VEC_NUM]; > + int ceqe_depth; > enum ib_mtu max_mtu; > u32 qpc_bt_num; > u32 srqc_bt_num; > @@ -623,6 +666,8 @@ struct hns_roce_hw { > int (*dereg_mr)(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr); > int (*destroy_cq)(struct ib_cq *ibcq); > int (*modify_cq)(struct ib_cq *cq, u16 cq_count, u16 cq_period); > + int (*init_eq)(struct hns_roce_dev *hr_dev); > + void (*cleanup_eq)(struct hns_roce_dev *hr_dev); > }; > > struct hns_roce_dev { > diff --git a/drivers/infiniband/hw/hns/hns_roce_eq.c b/drivers/infiniband/hw/hns/hns_roce_eq.c > deleted file mode 100644 > index d184431..0000000 > --- a/drivers/infiniband/hw/hns/hns_roce_eq.c > +++ /dev/null > @@ -1,759 +0,0 @@ > -/* > - * Copyright (c) 2016 Hisilicon Limited. > - * > - * This software is available to you under a choice of one of two > - * licenses. You may choose to be licensed under the terms of the GNU > - * General Public License (GPL) Version 2, available from the file > - * COPYING in the main directory of this source tree, or the > - * OpenIB.org BSD license below: > - * > - * 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. > - * > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS > - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN > - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN > - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE > - * SOFTWARE. > - */ > - > -#include <linux/platform_device.h> > -#include <linux/interrupt.h> > -#include "hns_roce_common.h" > -#include "hns_roce_device.h" > -#include "hns_roce_eq.h" > - > -static void eq_set_cons_index(struct hns_roce_eq *eq, int req_not) > -{ > - roce_raw_write((eq->cons_index & CONS_INDEX_MASK) | > - (req_not << eq->log_entries), eq->doorbell); > - /* Memory barrier */ > - mb(); > -} > - > -static struct hns_roce_aeqe *get_aeqe(struct hns_roce_eq *eq, u32 entry) > -{ > - unsigned long off = (entry & (eq->entries - 1)) * > - HNS_ROCE_AEQ_ENTRY_SIZE; > - > - return (struct hns_roce_aeqe *)((u8 *) > - (eq->buf_list[off / HNS_ROCE_BA_SIZE].buf) + > - off % HNS_ROCE_BA_SIZE); > -} > - > -static struct hns_roce_aeqe *next_aeqe_sw(struct hns_roce_eq *eq) > -{ > - struct hns_roce_aeqe *aeqe = get_aeqe(eq, eq->cons_index); > - > - return (roce_get_bit(aeqe->asyn, HNS_ROCE_AEQE_U32_4_OWNER_S) ^ > - !!(eq->cons_index & eq->entries)) ? aeqe : NULL; > -} > - > -static void hns_roce_wq_catas_err_handle(struct hns_roce_dev *hr_dev, > - struct hns_roce_aeqe *aeqe, int qpn) > -{ > - struct device *dev = &hr_dev->pdev->dev; > - > - dev_warn(dev, "Local Work Queue Catastrophic Error.\n"); > - switch (roce_get_field(aeqe->asyn, HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M, > - HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S)) { > - case HNS_ROCE_LWQCE_QPC_ERROR: > - dev_warn(dev, "QP %d, QPC error.\n", qpn); > - break; > - case HNS_ROCE_LWQCE_MTU_ERROR: > - dev_warn(dev, "QP %d, MTU error.\n", qpn); > - break; > - case HNS_ROCE_LWQCE_WQE_BA_ADDR_ERROR: > - dev_warn(dev, "QP %d, WQE BA addr error.\n", qpn); > - break; > - case HNS_ROCE_LWQCE_WQE_ADDR_ERROR: > - dev_warn(dev, "QP %d, WQE addr error.\n", qpn); > - break; > - case HNS_ROCE_LWQCE_SQ_WQE_SHIFT_ERROR: > - dev_warn(dev, "QP %d, WQE shift error\n", qpn); > - break; > - case HNS_ROCE_LWQCE_SL_ERROR: > - dev_warn(dev, "QP %d, SL error.\n", qpn); > - break; > - case HNS_ROCE_LWQCE_PORT_ERROR: > - dev_warn(dev, "QP %d, port error.\n", qpn); > - break; > - default: > - break; > - } > -} > - > -static void hns_roce_local_wq_access_err_handle(struct hns_roce_dev *hr_dev, > - struct hns_roce_aeqe *aeqe, > - int qpn) > -{ > - struct device *dev = &hr_dev->pdev->dev; > - > - dev_warn(dev, "Local Access Violation Work Queue Error.\n"); > - switch (roce_get_field(aeqe->asyn, HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M, > - HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S)) { > - case HNS_ROCE_LAVWQE_R_KEY_VIOLATION: > - dev_warn(dev, "QP %d, R_key violation.\n", qpn); > - break; > - case HNS_ROCE_LAVWQE_LENGTH_ERROR: > - dev_warn(dev, "QP %d, length error.\n", qpn); > - break; > - case HNS_ROCE_LAVWQE_VA_ERROR: > - dev_warn(dev, "QP %d, VA error.\n", qpn); > - break; > - case HNS_ROCE_LAVWQE_PD_ERROR: > - dev_err(dev, "QP %d, PD error.\n", qpn); > - break; > - case HNS_ROCE_LAVWQE_RW_ACC_ERROR: > - dev_warn(dev, "QP %d, rw acc error.\n", qpn); > - break; > - case HNS_ROCE_LAVWQE_KEY_STATE_ERROR: > - dev_warn(dev, "QP %d, key state error.\n", qpn); > - break; > - case HNS_ROCE_LAVWQE_MR_OPERATION_ERROR: > - dev_warn(dev, "QP %d, MR operation error.\n", qpn); > - break; > - default: > - break; > - } > -} > - > -static void hns_roce_qp_err_handle(struct hns_roce_dev *hr_dev, > - struct hns_roce_aeqe *aeqe, > - int event_type) > -{ > - struct device *dev = &hr_dev->pdev->dev; > - int phy_port; > - int qpn; > - > - qpn = roce_get_field(aeqe->event.qp_event.qp, > - HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_M, > - HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_S); > - phy_port = roce_get_field(aeqe->event.qp_event.qp, > - HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_M, > - HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_S); > - if (qpn <= 1) > - qpn = HNS_ROCE_MAX_PORTS * qpn + phy_port; > - > - switch (event_type) { > - case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR: > - dev_warn(dev, "Invalid Req Local Work Queue Error.\n" > - "QP %d, phy_port %d.\n", qpn, phy_port); > - break; > - case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR: > - hns_roce_wq_catas_err_handle(hr_dev, aeqe, qpn); > - break; > - case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR: > - hns_roce_local_wq_access_err_handle(hr_dev, aeqe, qpn); > - break; > - default: > - break; > - } > - > - hns_roce_qp_event(hr_dev, qpn, event_type); > -} > - > -static void hns_roce_cq_err_handle(struct hns_roce_dev *hr_dev, > - struct hns_roce_aeqe *aeqe, > - int event_type) > -{ > - struct device *dev = &hr_dev->pdev->dev; > - u32 cqn; > - > - cqn = le32_to_cpu(roce_get_field(aeqe->event.cq_event.cq, > - HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_M, > - HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_S)); > - > - switch (event_type) { > - case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR: > - dev_warn(dev, "CQ 0x%x access err.\n", cqn); > - break; > - case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW: > - dev_warn(dev, "CQ 0x%x overflow\n", cqn); > - break; > - case HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID: > - dev_warn(dev, "CQ 0x%x ID invalid.\n", cqn); > - break; > - default: > - break; > - } > - > - hns_roce_cq_event(hr_dev, cqn, event_type); > -} > - > -static void hns_roce_db_overflow_handle(struct hns_roce_dev *hr_dev, > - struct hns_roce_aeqe *aeqe) > -{ > - struct device *dev = &hr_dev->pdev->dev; > - > - switch (roce_get_field(aeqe->asyn, HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M, > - HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S)) { > - case HNS_ROCE_DB_SUBTYPE_SDB_OVF: > - dev_warn(dev, "SDB overflow.\n"); > - break; > - case HNS_ROCE_DB_SUBTYPE_SDB_ALM_OVF: > - dev_warn(dev, "SDB almost overflow.\n"); > - break; > - case HNS_ROCE_DB_SUBTYPE_SDB_ALM_EMP: > - dev_warn(dev, "SDB almost empty.\n"); > - break; > - case HNS_ROCE_DB_SUBTYPE_ODB_OVF: > - dev_warn(dev, "ODB overflow.\n"); > - break; > - case HNS_ROCE_DB_SUBTYPE_ODB_ALM_OVF: > - dev_warn(dev, "ODB almost overflow.\n"); > - break; > - case HNS_ROCE_DB_SUBTYPE_ODB_ALM_EMP: > - dev_warn(dev, "SDB almost empty.\n"); > - break; > - default: > - break; > - } > -} > - > -static int hns_roce_aeq_int(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq) > -{ > - struct device *dev = &hr_dev->pdev->dev; > - struct hns_roce_aeqe *aeqe; > - int aeqes_found = 0; > - int event_type; > - > - while ((aeqe = next_aeqe_sw(eq))) { > - dev_dbg(dev, "aeqe = %p, aeqe->asyn.event_type = 0x%lx\n", aeqe, > - roce_get_field(aeqe->asyn, > - HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M, > - HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S)); > - /* Memory barrier */ > - rmb(); > - > - event_type = roce_get_field(aeqe->asyn, > - HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M, > - HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S); > - switch (event_type) { > - case HNS_ROCE_EVENT_TYPE_PATH_MIG: > - dev_warn(dev, "PATH MIG not supported\n"); > - break; > - case HNS_ROCE_EVENT_TYPE_COMM_EST: > - dev_warn(dev, "COMMUNICATION established\n"); > - break; > - case HNS_ROCE_EVENT_TYPE_SQ_DRAINED: > - dev_warn(dev, "SQ DRAINED not supported\n"); > - break; > - case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED: > - dev_warn(dev, "PATH MIG failed\n"); > - break; > - case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR: > - case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR: > - case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR: > - hns_roce_qp_err_handle(hr_dev, aeqe, event_type); > - break; > - case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH: > - case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR: > - case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH: > - dev_warn(dev, "SRQ not support!\n"); > - break; > - case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR: > - case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW: > - case HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID: > - hns_roce_cq_err_handle(hr_dev, aeqe, event_type); > - break; > - case HNS_ROCE_EVENT_TYPE_PORT_CHANGE: > - dev_warn(dev, "port change.\n"); > - break; > - case HNS_ROCE_EVENT_TYPE_MB: > - hns_roce_cmd_event(hr_dev, > - le16_to_cpu(aeqe->event.cmd.token), > - aeqe->event.cmd.status, > - le64_to_cpu(aeqe->event.cmd.out_param > - )); > - break; > - case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW: > - hns_roce_db_overflow_handle(hr_dev, aeqe); > - break; > - case HNS_ROCE_EVENT_TYPE_CEQ_OVERFLOW: > - dev_warn(dev, "CEQ 0x%lx overflow.\n", > - roce_get_field(aeqe->event.ce_event.ceqe, > - HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_M, > - HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_S)); > - break; > - default: > - dev_warn(dev, "Unhandled event %d on EQ %d at index %u\n", > - event_type, eq->eqn, eq->cons_index); > - break; > - } > - > - eq->cons_index++; > - aeqes_found = 1; > - > - if (eq->cons_index > 2 * hr_dev->caps.aeqe_depth - 1) { > - dev_warn(dev, "cons_index overflow, set back to zero\n" > - ); > - eq->cons_index = 0; > - } > - } > - > - eq_set_cons_index(eq, 0); > - > - return aeqes_found; > -} > - > -static struct hns_roce_ceqe *get_ceqe(struct hns_roce_eq *eq, u32 entry) > -{ > - unsigned long off = (entry & (eq->entries - 1)) * > - HNS_ROCE_CEQ_ENTRY_SIZE; > - > - return (struct hns_roce_ceqe *)((u8 *) > - (eq->buf_list[off / HNS_ROCE_BA_SIZE].buf) + > - off % HNS_ROCE_BA_SIZE); > -} > - > -static struct hns_roce_ceqe *next_ceqe_sw(struct hns_roce_eq *eq) > -{ > - struct hns_roce_ceqe *ceqe = get_ceqe(eq, eq->cons_index); > - > - return (!!(roce_get_bit(ceqe->ceqe.comp, > - HNS_ROCE_CEQE_CEQE_COMP_OWNER_S))) ^ > - (!!(eq->cons_index & eq->entries)) ? ceqe : NULL; > -} > - > -static int hns_roce_ceq_int(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq) > -{ > - struct hns_roce_ceqe *ceqe; > - int ceqes_found = 0; > - u32 cqn; > - > - while ((ceqe = next_ceqe_sw(eq))) { > - /* Memory barrier */ > - rmb(); > - cqn = roce_get_field(ceqe->ceqe.comp, > - HNS_ROCE_CEQE_CEQE_COMP_CQN_M, > - HNS_ROCE_CEQE_CEQE_COMP_CQN_S); > - hns_roce_cq_completion(hr_dev, cqn); > - > - ++eq->cons_index; > - ceqes_found = 1; > - > - if (eq->cons_index > 2 * hr_dev->caps.ceqe_depth[eq->eqn] - 1) { > - dev_warn(&eq->hr_dev->pdev->dev, > - "cons_index overflow, set back to zero\n"); > - eq->cons_index = 0; > - } > - } > - > - eq_set_cons_index(eq, 0); > - > - return ceqes_found; > -} > - > -static int hns_roce_aeq_ovf_int(struct hns_roce_dev *hr_dev, > - struct hns_roce_eq *eq) > -{ > - struct device *dev = &eq->hr_dev->pdev->dev; > - int eqovf_found = 0; > - u32 caepaemask_val; > - u32 cealmovf_val; > - u32 caepaest_val; > - u32 aeshift_val; > - u32 ceshift_val; > - u32 cemask_val; > - int i = 0; > - > - /** > - * AEQ overflow ECC mult bit err CEQ overflow alarm > - * must clear interrupt, mask irq, clear irq, cancel mask operation > - */ > - aeshift_val = roce_read(hr_dev, ROCEE_CAEP_AEQC_AEQE_SHIFT_REG); > - > - if (roce_get_bit(aeshift_val, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQ_ALM_OVF_INT_ST_S) == 1) { > - dev_warn(dev, "AEQ overflow!\n"); > - > - /* Set mask */ > - caepaemask_val = roce_read(hr_dev, ROCEE_CAEP_AE_MASK_REG); > - roce_set_bit(caepaemask_val, > - ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S, > - HNS_ROCE_INT_MASK_ENABLE); > - roce_write(hr_dev, ROCEE_CAEP_AE_MASK_REG, caepaemask_val); > - > - /* Clear int state(INT_WC : write 1 clear) */ > - caepaest_val = roce_read(hr_dev, ROCEE_CAEP_AE_ST_REG); > - roce_set_bit(caepaest_val, > - ROCEE_CAEP_AE_ST_CAEP_AEQ_ALM_OVF_S, 1); > - roce_write(hr_dev, ROCEE_CAEP_AE_ST_REG, caepaest_val); > - > - /* Clear mask */ > - caepaemask_val = roce_read(hr_dev, ROCEE_CAEP_AE_MASK_REG); > - roce_set_bit(caepaemask_val, > - ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S, > - HNS_ROCE_INT_MASK_DISABLE); > - roce_write(hr_dev, ROCEE_CAEP_AE_MASK_REG, caepaemask_val); > - } > - > - /* CEQ almost overflow */ > - for (i = 0; i < hr_dev->caps.num_comp_vectors; i++) { > - ceshift_val = roce_read(hr_dev, ROCEE_CAEP_CEQC_SHIFT_0_REG + > - i * CEQ_REG_OFFSET); > - > - if (roce_get_bit(ceshift_val, > - ROCEE_CAEP_CEQC_SHIFT_CAEP_CEQ_ALM_OVF_INT_ST_S) == 1) { > - dev_warn(dev, "CEQ[%d] almost overflow!\n", i); > - eqovf_found++; > - > - /* Set mask */ > - cemask_val = roce_read(hr_dev, > - ROCEE_CAEP_CE_IRQ_MASK_0_REG + > - i * CEQ_REG_OFFSET); > - roce_set_bit(cemask_val, > - ROCEE_CAEP_CE_IRQ_MASK_CAEP_CEQ_ALM_OVF_MASK_S, > - HNS_ROCE_INT_MASK_ENABLE); > - roce_write(hr_dev, ROCEE_CAEP_CE_IRQ_MASK_0_REG + > - i * CEQ_REG_OFFSET, cemask_val); > - > - /* Clear int state(INT_WC : write 1 clear) */ > - cealmovf_val = roce_read(hr_dev, > - ROCEE_CAEP_CEQ_ALM_OVF_0_REG + > - i * CEQ_REG_OFFSET); > - roce_set_bit(cealmovf_val, > - ROCEE_CAEP_CEQ_ALM_OVF_CAEP_CEQ_ALM_OVF_S, > - 1); > - roce_write(hr_dev, ROCEE_CAEP_CEQ_ALM_OVF_0_REG + > - i * CEQ_REG_OFFSET, cealmovf_val); > - > - /* Clear mask */ > - cemask_val = roce_read(hr_dev, > - ROCEE_CAEP_CE_IRQ_MASK_0_REG + > - i * CEQ_REG_OFFSET); > - roce_set_bit(cemask_val, > - ROCEE_CAEP_CE_IRQ_MASK_CAEP_CEQ_ALM_OVF_MASK_S, > - HNS_ROCE_INT_MASK_DISABLE); > - roce_write(hr_dev, ROCEE_CAEP_CE_IRQ_MASK_0_REG + > - i * CEQ_REG_OFFSET, cemask_val); > - } > - } > - > - /* ECC multi-bit error alarm */ > - dev_warn(dev, "ECC UCERR ALARM: 0x%x, 0x%x, 0x%x\n", > - roce_read(hr_dev, ROCEE_ECC_UCERR_ALM0_REG), > - roce_read(hr_dev, ROCEE_ECC_UCERR_ALM1_REG), > - roce_read(hr_dev, ROCEE_ECC_UCERR_ALM2_REG)); > - > - dev_warn(dev, "ECC CERR ALARM: 0x%x, 0x%x, 0x%x\n", > - roce_read(hr_dev, ROCEE_ECC_CERR_ALM0_REG), > - roce_read(hr_dev, ROCEE_ECC_CERR_ALM1_REG), > - roce_read(hr_dev, ROCEE_ECC_CERR_ALM2_REG)); > - > - return eqovf_found; > -} > - > -static int hns_roce_eq_int(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq) > -{ > - int eqes_found = 0; > - > - if (likely(eq->type_flag == HNS_ROCE_CEQ)) > - /* CEQ irq routine, CEQ is pulse irq, not clear */ > - eqes_found = hns_roce_ceq_int(hr_dev, eq); > - else if (likely(eq->type_flag == HNS_ROCE_AEQ)) > - /* AEQ irq routine, AEQ is pulse irq, not clear */ > - eqes_found = hns_roce_aeq_int(hr_dev, eq); > - else > - /* AEQ queue overflow irq */ > - eqes_found = hns_roce_aeq_ovf_int(hr_dev, eq); > - > - return eqes_found; > -} > - > -static irqreturn_t hns_roce_msi_x_interrupt(int irq, void *eq_ptr) > -{ > - int int_work = 0; > - struct hns_roce_eq *eq = eq_ptr; > - struct hns_roce_dev *hr_dev = eq->hr_dev; > - > - int_work = hns_roce_eq_int(hr_dev, eq); > - > - return IRQ_RETVAL(int_work); > -} > - > -static void hns_roce_enable_eq(struct hns_roce_dev *hr_dev, int eq_num, > - int enable_flag) > -{ > - void __iomem *eqc = hr_dev->eq_table.eqc_base[eq_num]; > - u32 val; > - > - val = readl(eqc); > - > - if (enable_flag) > - roce_set_field(val, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S, > - HNS_ROCE_EQ_STAT_VALID); > - else > - roce_set_field(val, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S, > - HNS_ROCE_EQ_STAT_INVALID); > - writel(val, eqc); > -} > - > -static int hns_roce_create_eq(struct hns_roce_dev *hr_dev, > - struct hns_roce_eq *eq) > -{ > - void __iomem *eqc = hr_dev->eq_table.eqc_base[eq->eqn]; > - struct device *dev = &hr_dev->pdev->dev; > - dma_addr_t tmp_dma_addr; > - u32 eqconsindx_val = 0; > - u32 eqcuridx_val = 0; > - u32 eqshift_val = 0; > - int num_bas = 0; > - int ret; > - int i; > - > - num_bas = (PAGE_ALIGN(eq->entries * eq->eqe_size) + > - HNS_ROCE_BA_SIZE - 1) / HNS_ROCE_BA_SIZE; > - > - if ((eq->entries * eq->eqe_size) > HNS_ROCE_BA_SIZE) { > - dev_err(dev, "[error]eq buf %d gt ba size(%d) need bas=%d\n", > - (eq->entries * eq->eqe_size), HNS_ROCE_BA_SIZE, > - num_bas); > - return -EINVAL; > - } > - > - eq->buf_list = kcalloc(num_bas, sizeof(*eq->buf_list), GFP_KERNEL); > - if (!eq->buf_list) > - return -ENOMEM; > - > - for (i = 0; i < num_bas; ++i) { > - eq->buf_list[i].buf = dma_alloc_coherent(dev, HNS_ROCE_BA_SIZE, > - &tmp_dma_addr, > - GFP_KERNEL); > - if (!eq->buf_list[i].buf) { > - ret = -ENOMEM; > - goto err_out_free_pages; > - } > - > - eq->buf_list[i].map = tmp_dma_addr; > - memset(eq->buf_list[i].buf, 0, HNS_ROCE_BA_SIZE); > - } > - eq->cons_index = 0; > - roce_set_field(eqshift_val, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S, > - HNS_ROCE_EQ_STAT_INVALID); > - roce_set_field(eqshift_val, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_M, > - ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_S, > - eq->log_entries); > - writel(eqshift_val, eqc); > - > - /* Configure eq extended address 12~44bit */ > - writel((u32)(eq->buf_list[0].map >> 12), eqc + 4); > - > - /* > - * Configure eq extended address 45~49 bit. > - * 44 = 32 + 12, When evaluating addr to hardware, shift 12 because of > - * using 4K page, and shift more 32 because of > - * caculating the high 32 bit value evaluated to hardware. > - */ > - roce_set_field(eqcuridx_val, ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_M, > - ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_S, > - eq->buf_list[0].map >> 44); > - roce_set_field(eqcuridx_val, > - ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_M, > - ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_S, 0); > - writel(eqcuridx_val, eqc + 8); > - > - /* Configure eq consumer index */ > - roce_set_field(eqconsindx_val, > - ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_M, > - ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_S, 0); > - writel(eqconsindx_val, eqc + 0xc); > - > - return 0; > - > -err_out_free_pages: > - for (i = i - 1; i >= 0; i--) > - dma_free_coherent(dev, HNS_ROCE_BA_SIZE, eq->buf_list[i].buf, > - eq->buf_list[i].map); > - > - kfree(eq->buf_list); > - return ret; > -} > - > -static void hns_roce_free_eq(struct hns_roce_dev *hr_dev, > - struct hns_roce_eq *eq) > -{ > - int i = 0; > - int npages = (PAGE_ALIGN(eq->eqe_size * eq->entries) + > - HNS_ROCE_BA_SIZE - 1) / HNS_ROCE_BA_SIZE; > - > - if (!eq->buf_list) > - return; > - > - for (i = 0; i < npages; ++i) > - dma_free_coherent(&hr_dev->pdev->dev, HNS_ROCE_BA_SIZE, > - eq->buf_list[i].buf, eq->buf_list[i].map); > - > - kfree(eq->buf_list); > -} > - > -static void hns_roce_int_mask_en(struct hns_roce_dev *hr_dev) > -{ > - int i = 0; > - u32 aemask_val; > - int masken = 0; > - > - /* AEQ INT */ > - aemask_val = roce_read(hr_dev, ROCEE_CAEP_AE_MASK_REG); > - roce_set_bit(aemask_val, ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S, > - masken); > - roce_set_bit(aemask_val, ROCEE_CAEP_AE_MASK_CAEP_AE_IRQ_MASK_S, masken); > - roce_write(hr_dev, ROCEE_CAEP_AE_MASK_REG, aemask_val); > - > - /* CEQ INT */ > - for (i = 0; i < hr_dev->caps.num_comp_vectors; i++) { > - /* IRQ mask */ > - roce_write(hr_dev, ROCEE_CAEP_CE_IRQ_MASK_0_REG + > - i * CEQ_REG_OFFSET, masken); > - } > -} > - > -static void hns_roce_ce_int_default_cfg(struct hns_roce_dev *hr_dev) > -{ > - /* Configure ce int interval */ > - roce_write(hr_dev, ROCEE_CAEP_CE_INTERVAL_CFG_REG, > - HNS_ROCE_CEQ_DEFAULT_INTERVAL); > - > - /* Configure ce int burst num */ > - roce_write(hr_dev, ROCEE_CAEP_CE_BURST_NUM_CFG_REG, > - HNS_ROCE_CEQ_DEFAULT_BURST_NUM); > -} > - > -int hns_roce_init_eq_table(struct hns_roce_dev *hr_dev) > -{ > - struct hns_roce_eq_table *eq_table = &hr_dev->eq_table; > - struct device *dev = &hr_dev->pdev->dev; > - struct hns_roce_eq *eq = NULL; > - int eq_num = 0; > - int ret = 0; > - int i = 0; > - int j = 0; > - > - eq_num = hr_dev->caps.num_comp_vectors + hr_dev->caps.num_aeq_vectors; > - eq_table->eq = kcalloc(eq_num, sizeof(*eq_table->eq), GFP_KERNEL); > - if (!eq_table->eq) > - return -ENOMEM; > - > - eq_table->eqc_base = kcalloc(eq_num, sizeof(*eq_table->eqc_base), > - GFP_KERNEL); > - if (!eq_table->eqc_base) { > - ret = -ENOMEM; > - goto err_eqc_base_alloc_fail; > - } > - > - for (i = 0; i < eq_num; i++) { > - eq = &eq_table->eq[i]; > - eq->hr_dev = hr_dev; > - eq->eqn = i; > - eq->irq = hr_dev->irq[i]; > - eq->log_page_size = PAGE_SHIFT; > - > - if (i < hr_dev->caps.num_comp_vectors) { > - /* CEQ */ > - eq_table->eqc_base[i] = hr_dev->reg_base + > - ROCEE_CAEP_CEQC_SHIFT_0_REG + > - HNS_ROCE_CEQC_REG_OFFSET * i; > - eq->type_flag = HNS_ROCE_CEQ; > - eq->doorbell = hr_dev->reg_base + > - ROCEE_CAEP_CEQC_CONS_IDX_0_REG + > - HNS_ROCE_CEQC_REG_OFFSET * i; > - eq->entries = hr_dev->caps.ceqe_depth[i]; > - eq->log_entries = ilog2(eq->entries); > - eq->eqe_size = sizeof(struct hns_roce_ceqe); > - } else { > - /* AEQ */ > - eq_table->eqc_base[i] = hr_dev->reg_base + > - ROCEE_CAEP_AEQC_AEQE_SHIFT_REG; > - eq->type_flag = HNS_ROCE_AEQ; > - eq->doorbell = hr_dev->reg_base + > - ROCEE_CAEP_AEQE_CONS_IDX_REG; > - eq->entries = hr_dev->caps.aeqe_depth; > - eq->log_entries = ilog2(eq->entries); > - eq->eqe_size = sizeof(struct hns_roce_aeqe); > - } > - } > - > - /* Disable irq */ > - hns_roce_int_mask_en(hr_dev); > - > - /* Configure CE irq interval and burst num */ > - hns_roce_ce_int_default_cfg(hr_dev); > - > - for (i = 0; i < eq_num; i++) { > - ret = hns_roce_create_eq(hr_dev, &eq_table->eq[i]); > - if (ret) { > - dev_err(dev, "eq create failed\n"); > - goto err_create_eq_fail; > - } > - } > - > - for (j = 0; j < eq_num; j++) { > - ret = request_irq(eq_table->eq[j].irq, hns_roce_msi_x_interrupt, > - 0, hr_dev->irq_names[j], eq_table->eq + j); > - if (ret) { > - dev_err(dev, "request irq error!\n"); > - goto err_request_irq_fail; > - } > - } > - > - for (i = 0; i < eq_num; i++) > - hns_roce_enable_eq(hr_dev, i, EQ_ENABLE); > - > - return 0; > - > -err_request_irq_fail: > - for (j = j - 1; j >= 0; j--) > - free_irq(eq_table->eq[j].irq, eq_table->eq + j); > - > -err_create_eq_fail: > - for (i = i - 1; i >= 0; i--) > - hns_roce_free_eq(hr_dev, &eq_table->eq[i]); > - > - kfree(eq_table->eqc_base); > - > -err_eqc_base_alloc_fail: > - kfree(eq_table->eq); > - > - return ret; > -} > - > -void hns_roce_cleanup_eq_table(struct hns_roce_dev *hr_dev) > -{ > - int i; > - int eq_num; > - struct hns_roce_eq_table *eq_table = &hr_dev->eq_table; > - > - eq_num = hr_dev->caps.num_comp_vectors + hr_dev->caps.num_aeq_vectors; > - for (i = 0; i < eq_num; i++) { > - /* Disable EQ */ > - hns_roce_enable_eq(hr_dev, i, EQ_DISABLE); > - > - free_irq(eq_table->eq[i].irq, eq_table->eq + i); > - > - hns_roce_free_eq(hr_dev, &eq_table->eq[i]); > - } > - > - kfree(eq_table->eqc_base); > - kfree(eq_table->eq); > -} > diff --git a/drivers/infiniband/hw/hns/hns_roce_eq.h b/drivers/infiniband/hw/hns/hns_roce_eq.h > deleted file mode 100644 > index c6d212d..0000000 > --- a/drivers/infiniband/hw/hns/hns_roce_eq.h > +++ /dev/null > @@ -1,134 +0,0 @@ > -/* > - * Copyright (c) 2016 Hisilicon Limited. > - * > - * This software is available to you under a choice of one of two > - * licenses. You may choose to be licensed under the terms of the GNU > - * General Public License (GPL) Version 2, available from the file > - * COPYING in the main directory of this source tree, or the > - * OpenIB.org BSD license below: > - * > - * 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. > - * > - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS > - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN > - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN > - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE > - * SOFTWARE. > - */ > - > -#ifndef _HNS_ROCE_EQ_H > -#define _HNS_ROCE_EQ_H > - > -#define HNS_ROCE_CEQ 1 > -#define HNS_ROCE_AEQ 2 > - > -#define HNS_ROCE_CEQ_ENTRY_SIZE 0x4 > -#define HNS_ROCE_AEQ_ENTRY_SIZE 0x10 > -#define HNS_ROCE_CEQC_REG_OFFSET 0x18 > - > -#define HNS_ROCE_CEQ_DEFAULT_INTERVAL 0x10 > -#define HNS_ROCE_CEQ_DEFAULT_BURST_NUM 0x10 > - > -#define HNS_ROCE_INT_MASK_DISABLE 0 > -#define HNS_ROCE_INT_MASK_ENABLE 1 > - > -#define EQ_ENABLE 1 > -#define EQ_DISABLE 0 > -#define CONS_INDEX_MASK 0xffff > - > -#define CEQ_REG_OFFSET 0x18 > - > -enum { > - HNS_ROCE_EQ_STAT_INVALID = 0, > - HNS_ROCE_EQ_STAT_VALID = 2, > -}; > - > -struct hns_roce_aeqe { > - u32 asyn; > - union { > - struct { > - u32 qp; > - u32 rsv0; > - u32 rsv1; > - } qp_event; > - > - struct { > - u32 cq; > - u32 rsv0; > - u32 rsv1; > - } cq_event; > - > - struct { > - u32 port; > - u32 rsv0; > - u32 rsv1; > - } port_event; > - > - struct { > - u32 ceqe; > - u32 rsv0; > - u32 rsv1; > - } ce_event; > - > - struct { > - __le64 out_param; > - __le16 token; > - u8 status; > - u8 rsv0; > - } __packed cmd; > - } event; > -}; > - > -#define HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S 16 > -#define HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M \ > - (((1UL << 8) - 1) << HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S) > - > -#define HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S 24 > -#define HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M \ > - (((1UL << 7) - 1) << HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S) > - > -#define HNS_ROCE_AEQE_U32_4_OWNER_S 31 > - > -#define HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_S 0 > -#define HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_M \ > - (((1UL << 24) - 1) << HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_S) > - > -#define HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_S 25 > -#define HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_M \ > - (((1UL << 3) - 1) << HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_S) > - > -#define HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_S 0 > -#define HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_M \ > - (((1UL << 16) - 1) << HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_S) > - > -#define HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_S 0 > -#define HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_M \ > - (((1UL << 5) - 1) << HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_S) > - > -struct hns_roce_ceqe { > - union { > - int comp; > - } ceqe; > -}; > - > -#define HNS_ROCE_CEQE_CEQE_COMP_OWNER_S 0 > - > -#define HNS_ROCE_CEQE_CEQE_COMP_CQN_S 16 > -#define HNS_ROCE_CEQE_CEQE_COMP_CQN_M \ > - (((1UL << 16) - 1) << HNS_ROCE_CEQE_CEQE_COMP_CQN_S) > - > -#endif /* _HNS_ROCE_EQ_H */ > diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c > index af27168..6100ace 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c > +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c > @@ -33,6 +33,7 @@ > #include <linux/platform_device.h> > #include <linux/acpi.h> > #include <linux/etherdevice.h> > +#include <linux/interrupt.h> > #include <linux/of.h> > #include <linux/of_platform.h> > #include <rdma/ib_umem.h> > @@ -1492,9 +1493,9 @@ static int hns_roce_v1_profile(struct hns_roce_dev *hr_dev) > caps->max_sq_inline = HNS_ROCE_V1_INLINE_SIZE; > caps->num_uars = HNS_ROCE_V1_UAR_NUM; > caps->phy_num_uars = HNS_ROCE_V1_PHY_UAR_NUM; > - caps->num_aeq_vectors = HNS_ROCE_AEQE_VEC_NUM; > - caps->num_comp_vectors = HNS_ROCE_COMP_VEC_NUM; > - caps->num_other_vectors = HNS_ROCE_AEQE_OF_VEC_NUM; > + caps->num_aeq_vectors = HNS_ROCE_V1_AEQE_VEC_NUM; > + caps->num_comp_vectors = HNS_ROCE_V1_COMP_VEC_NUM; > + caps->num_other_vectors = HNS_ROCE_V1_ABNORMAL_VEC_NUM; > caps->num_mtpts = HNS_ROCE_V1_MAX_MTPT_NUM; > caps->num_mtt_segs = HNS_ROCE_V1_MAX_MTT_SEGS; > caps->num_pds = HNS_ROCE_V1_MAX_PD_NUM; > @@ -1529,10 +1530,8 @@ static int hns_roce_v1_profile(struct hns_roce_dev *hr_dev) > caps->num_ports + 1; > } > > - for (i = 0; i < caps->num_comp_vectors; i++) > - caps->ceqe_depth[i] = HNS_ROCE_V1_NUM_COMP_EQE; > - > - caps->aeqe_depth = HNS_ROCE_V1_NUM_ASYNC_EQE; > + caps->ceqe_depth = HNS_ROCE_V1_COMP_EQE_NUM; > + caps->aeqe_depth = HNS_ROCE_V1_ASYNC_EQE_NUM; > caps->local_ca_ack_delay = le32_to_cpu(roce_read(hr_dev, > ROCEE_ACK_DELAY_REG)); > caps->max_mtu = IB_MTU_2048; > @@ -3960,6 +3959,727 @@ static int hns_roce_v1_destroy_cq(struct ib_cq *ibcq) > return ret; > } > > +static void set_eq_cons_index_v1(struct hns_roce_eq *eq, int req_not) > +{ > + roce_raw_write((eq->cons_index & HNS_ROCE_V1_CONS_IDX_M) | > + (req_not << eq->log_entries), eq->doorbell); > + /* Memory barrier */ > + mb(); > +} > + > +static void hns_roce_v1_wq_catas_err_handle(struct hns_roce_dev *hr_dev, > + struct hns_roce_aeqe *aeqe, int qpn) > +{ > + struct device *dev = &hr_dev->pdev->dev; > + > + dev_warn(dev, "Local Work Queue Catastrophic Error.\n"); > + switch (roce_get_field(aeqe->asyn, HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M, > + HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S)) { > + case HNS_ROCE_LWQCE_QPC_ERROR: > + dev_warn(dev, "QP %d, QPC error.\n", qpn); > + break; > + case HNS_ROCE_LWQCE_MTU_ERROR: > + dev_warn(dev, "QP %d, MTU error.\n", qpn); > + break; > + case HNS_ROCE_LWQCE_WQE_BA_ADDR_ERROR: > + dev_warn(dev, "QP %d, WQE BA addr error.\n", qpn); > + break; > + case HNS_ROCE_LWQCE_WQE_ADDR_ERROR: > + dev_warn(dev, "QP %d, WQE addr error.\n", qpn); > + break; > + case HNS_ROCE_LWQCE_SQ_WQE_SHIFT_ERROR: > + dev_warn(dev, "QP %d, WQE shift error\n", qpn); > + break; > + case HNS_ROCE_LWQCE_SL_ERROR: > + dev_warn(dev, "QP %d, SL error.\n", qpn); > + break; > + case HNS_ROCE_LWQCE_PORT_ERROR: > + dev_warn(dev, "QP %d, port error.\n", qpn); > + break; > + default: > + break; > + } > +} > + > +static void hns_roce_v1_local_wq_access_err_handle(struct hns_roce_dev *hr_dev, > + struct hns_roce_aeqe *aeqe, > + int qpn) > +{ > + struct device *dev = &hr_dev->pdev->dev; > + > + dev_warn(dev, "Local Access Violation Work Queue Error.\n"); > + switch (roce_get_field(aeqe->asyn, HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M, > + HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S)) { > + case HNS_ROCE_LAVWQE_R_KEY_VIOLATION: > + dev_warn(dev, "QP %d, R_key violation.\n", qpn); > + break; > + case HNS_ROCE_LAVWQE_LENGTH_ERROR: > + dev_warn(dev, "QP %d, length error.\n", qpn); > + break; > + case HNS_ROCE_LAVWQE_VA_ERROR: > + dev_warn(dev, "QP %d, VA error.\n", qpn); > + break; > + case HNS_ROCE_LAVWQE_PD_ERROR: > + dev_err(dev, "QP %d, PD error.\n", qpn); > + break; > + case HNS_ROCE_LAVWQE_RW_ACC_ERROR: > + dev_warn(dev, "QP %d, rw acc error.\n", qpn); > + break; > + case HNS_ROCE_LAVWQE_KEY_STATE_ERROR: > + dev_warn(dev, "QP %d, key state error.\n", qpn); > + break; > + case HNS_ROCE_LAVWQE_MR_OPERATION_ERROR: > + dev_warn(dev, "QP %d, MR operation error.\n", qpn); > + break; > + default: > + break; > + } > +} > + > +static void hns_roce_v1_qp_err_handle(struct hns_roce_dev *hr_dev, > + struct hns_roce_aeqe *aeqe, > + int event_type) > +{ > + struct device *dev = &hr_dev->pdev->dev; > + int phy_port; > + int qpn; > + > + qpn = roce_get_field(aeqe->event.qp_event.qp, > + HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_M, > + HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_S); > + phy_port = roce_get_field(aeqe->event.qp_event.qp, > + HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_M, > + HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_S); > + if (qpn <= 1) > + qpn = HNS_ROCE_MAX_PORTS * qpn + phy_port; > + > + switch (event_type) { > + case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR: > + dev_warn(dev, "Invalid Req Local Work Queue Error.\n" > + "QP %d, phy_port %d.\n", qpn, phy_port); > + break; > + case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR: > + hns_roce_v1_wq_catas_err_handle(hr_dev, aeqe, qpn); > + break; > + case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR: > + hns_roce_v1_local_wq_access_err_handle(hr_dev, aeqe, qpn); > + break; > + default: > + break; > + } > + > + hns_roce_qp_event(hr_dev, qpn, event_type); > +} > + > +static void hns_roce_v1_cq_err_handle(struct hns_roce_dev *hr_dev, > + struct hns_roce_aeqe *aeqe, > + int event_type) > +{ > + struct device *dev = &hr_dev->pdev->dev; > + u32 cqn; > + > + cqn = le32_to_cpu(roce_get_field(aeqe->event.cq_event.cq, > + HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_M, > + HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_S)); > + > + switch (event_type) { > + case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR: > + dev_warn(dev, "CQ 0x%x access err.\n", cqn); > + break; > + case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW: > + dev_warn(dev, "CQ 0x%x overflow\n", cqn); > + break; > + case HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID: > + dev_warn(dev, "CQ 0x%x ID invalid.\n", cqn); > + break; > + default: > + break; > + } > + > + hns_roce_cq_event(hr_dev, cqn, event_type); > +} > + > +static void hns_roce_v1_db_overflow_handle(struct hns_roce_dev *hr_dev, > + struct hns_roce_aeqe *aeqe) > +{ > + struct device *dev = &hr_dev->pdev->dev; > + > + switch (roce_get_field(aeqe->asyn, HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M, > + HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S)) { > + case HNS_ROCE_DB_SUBTYPE_SDB_OVF: > + dev_warn(dev, "SDB overflow.\n"); > + break; > + case HNS_ROCE_DB_SUBTYPE_SDB_ALM_OVF: > + dev_warn(dev, "SDB almost overflow.\n"); > + break; > + case HNS_ROCE_DB_SUBTYPE_SDB_ALM_EMP: > + dev_warn(dev, "SDB almost empty.\n"); > + break; > + case HNS_ROCE_DB_SUBTYPE_ODB_OVF: > + dev_warn(dev, "ODB overflow.\n"); > + break; > + case HNS_ROCE_DB_SUBTYPE_ODB_ALM_OVF: > + dev_warn(dev, "ODB almost overflow.\n"); > + break; > + case HNS_ROCE_DB_SUBTYPE_ODB_ALM_EMP: > + dev_warn(dev, "SDB almost empty.\n"); > + break; > + default: > + break; > + } > +} > + > +static struct hns_roce_aeqe *get_aeqe_v1(struct hns_roce_eq *eq, u32 entry) > +{ > + unsigned long off = (entry & (eq->entries - 1)) * > + HNS_ROCE_AEQ_ENTRY_SIZE; > + > + return (struct hns_roce_aeqe *)((u8 *) > + (eq->buf_list[off / HNS_ROCE_BA_SIZE].buf) + > + off % HNS_ROCE_BA_SIZE); > +} > + > +static struct hns_roce_aeqe *next_aeqe_sw_v1(struct hns_roce_eq *eq) > +{ > + struct hns_roce_aeqe *aeqe = get_aeqe_v1(eq, eq->cons_index); > + > + return (roce_get_bit(aeqe->asyn, HNS_ROCE_AEQE_U32_4_OWNER_S) ^ > + !!(eq->cons_index & eq->entries)) ? aeqe : NULL; > +} > + > +static int hns_roce_v1_aeq_int(struct hns_roce_dev *hr_dev, > + struct hns_roce_eq *eq) > +{ > + struct device *dev = &hr_dev->pdev->dev; > + struct hns_roce_aeqe *aeqe; > + int aeqes_found = 0; > + int event_type; > + > + while ((aeqe = next_aeqe_sw_v1(eq))) { > + dev_dbg(dev, "aeqe = %p, aeqe->asyn.event_type = 0x%lx\n", aeqe, > + roce_get_field(aeqe->asyn, > + HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M, > + HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S)); > + /* Memory barrier */ > + rmb(); > + > + event_type = roce_get_field(aeqe->asyn, > + HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M, > + HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S); > + switch (event_type) { > + case HNS_ROCE_EVENT_TYPE_PATH_MIG: > + dev_warn(dev, "PATH MIG not supported\n"); > + break; > + case HNS_ROCE_EVENT_TYPE_COMM_EST: > + dev_warn(dev, "COMMUNICATION established\n"); > + break; > + case HNS_ROCE_EVENT_TYPE_SQ_DRAINED: > + dev_warn(dev, "SQ DRAINED not supported\n"); > + break; > + case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED: > + dev_warn(dev, "PATH MIG failed\n"); > + break; > + case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR: > + case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR: > + case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR: > + hns_roce_v1_qp_err_handle(hr_dev, aeqe, event_type); > + break; > + case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH: > + case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR: > + case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH: > + dev_warn(dev, "SRQ not support!\n"); > + break; > + case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR: > + case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW: > + case HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID: > + hns_roce_v1_cq_err_handle(hr_dev, aeqe, event_type); > + break; > + case HNS_ROCE_EVENT_TYPE_PORT_CHANGE: > + dev_warn(dev, "port change.\n"); > + break; > + case HNS_ROCE_EVENT_TYPE_MB: > + hns_roce_cmd_event(hr_dev, > + le16_to_cpu(aeqe->event.cmd.token), > + aeqe->event.cmd.status, > + le64_to_cpu(aeqe->event.cmd.out_param > + )); > + break; > + case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW: > + hns_roce_v1_db_overflow_handle(hr_dev, aeqe); > + break; > + case HNS_ROCE_EVENT_TYPE_CEQ_OVERFLOW: > + dev_warn(dev, "CEQ 0x%lx overflow.\n", > + roce_get_field(aeqe->event.ce_event.ceqe, > + HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_M, > + HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_S)); > + break; > + default: > + dev_warn(dev, "Unhandled event %d on EQ %d at idx %u.\n", > + event_type, eq->eqn, eq->cons_index); > + break; > + } > + > + eq->cons_index++; > + aeqes_found = 1; > + > + if (eq->cons_index > 2 * hr_dev->caps.aeqe_depth - 1) { > + dev_warn(dev, "cons_index overflow, set back to 0.\n"); > + eq->cons_index = 0; > + } > + } > + > + set_eq_cons_index_v1(eq, 0); > + > + return aeqes_found; > +} > + > +static struct hns_roce_ceqe *get_ceqe_v1(struct hns_roce_eq *eq, u32 entry) > +{ > + unsigned long off = (entry & (eq->entries - 1)) * > + HNS_ROCE_CEQ_ENTRY_SIZE; > + > + return (struct hns_roce_ceqe *)((u8 *) > + (eq->buf_list[off / HNS_ROCE_BA_SIZE].buf) + > + off % HNS_ROCE_BA_SIZE); > +} > + > +static struct hns_roce_ceqe *next_ceqe_sw_v1(struct hns_roce_eq *eq) > +{ > + struct hns_roce_ceqe *ceqe = get_ceqe_v1(eq, eq->cons_index); > + > + return (!!(roce_get_bit(ceqe->comp, > + HNS_ROCE_CEQE_CEQE_COMP_OWNER_S))) ^ > + (!!(eq->cons_index & eq->entries)) ? ceqe : NULL; > +} > + > +static int hns_roce_v1_ceq_int(struct hns_roce_dev *hr_dev, > + struct hns_roce_eq *eq) > +{ > + struct hns_roce_ceqe *ceqe; > + int ceqes_found = 0; > + u32 cqn; > + > + while ((ceqe = next_ceqe_sw_v1(eq))) { > + /* Memory barrier */ > + rmb(); > + cqn = roce_get_field(ceqe->comp, > + HNS_ROCE_CEQE_CEQE_COMP_CQN_M, > + HNS_ROCE_CEQE_CEQE_COMP_CQN_S); > + hns_roce_cq_completion(hr_dev, cqn); > + > + ++eq->cons_index; > + ceqes_found = 1; > + > + if (eq->cons_index > 2 * hr_dev->caps.ceqe_depth - 1) { > + dev_warn(&eq->hr_dev->pdev->dev, > + "cons_index overflow, set back to 0.\n"); > + eq->cons_index = 0; > + } > + } > + > + set_eq_cons_index_v1(eq, 0); > + > + return ceqes_found; > +} > + > +static irqreturn_t hns_roce_v1_msix_interrupt_eq(int irq, void *eq_ptr) > +{ > + struct hns_roce_eq *eq = eq_ptr; > + struct hns_roce_dev *hr_dev = eq->hr_dev; > + int int_work = 0; > + > + if (eq->type_flag == HNS_ROCE_CEQ) > + /* CEQ irq routine, CEQ is pulse irq, not clear */ > + int_work = hns_roce_v1_ceq_int(hr_dev, eq); > + else > + /* AEQ irq routine, AEQ is pulse irq, not clear */ > + int_work = hns_roce_v1_aeq_int(hr_dev, eq); > + > + return IRQ_RETVAL(int_work); > +} > + > +static irqreturn_t hns_roce_v1_msix_interrupt_abn(int irq, void *dev_id) > +{ > + struct hns_roce_dev *hr_dev = dev_id; > + struct device *dev = &hr_dev->pdev->dev; > + int int_work = 0; > + u32 caepaemask_val; > + u32 cealmovf_val; > + u32 caepaest_val; > + u32 aeshift_val; > + u32 ceshift_val; > + u32 cemask_val; > + int i; > + > + /* > + * Abnormal interrupt: > + * AEQ overflow, ECC multi-bit err, CEQ overflow must clear > + * interrupt, mask irq, clear irq, cancel mask operation > + */ > + aeshift_val = roce_read(hr_dev, ROCEE_CAEP_AEQC_AEQE_SHIFT_REG); > + > + /* AEQE overflow */ > + if (roce_get_bit(aeshift_val, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQ_ALM_OVF_INT_ST_S) == 1) { > + dev_warn(dev, "AEQ overflow!\n"); > + > + /* Set mask */ > + caepaemask_val = roce_read(hr_dev, ROCEE_CAEP_AE_MASK_REG); > + roce_set_bit(caepaemask_val, > + ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S, > + HNS_ROCE_INT_MASK_ENABLE); > + roce_write(hr_dev, ROCEE_CAEP_AE_MASK_REG, caepaemask_val); > + > + /* Clear int state(INT_WC : write 1 clear) */ > + caepaest_val = roce_read(hr_dev, ROCEE_CAEP_AE_ST_REG); > + roce_set_bit(caepaest_val, > + ROCEE_CAEP_AE_ST_CAEP_AEQ_ALM_OVF_S, 1); > + roce_write(hr_dev, ROCEE_CAEP_AE_ST_REG, caepaest_val); > + > + /* Clear mask */ > + caepaemask_val = roce_read(hr_dev, ROCEE_CAEP_AE_MASK_REG); > + roce_set_bit(caepaemask_val, > + ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S, > + HNS_ROCE_INT_MASK_DISABLE); > + roce_write(hr_dev, ROCEE_CAEP_AE_MASK_REG, caepaemask_val); > + } > + > + /* CEQ almost overflow */ > + for (i = 0; i < hr_dev->caps.num_comp_vectors; i++) { > + ceshift_val = roce_read(hr_dev, ROCEE_CAEP_CEQC_SHIFT_0_REG + > + i * CEQ_REG_OFFSET); > + > + if (roce_get_bit(ceshift_val, > + ROCEE_CAEP_CEQC_SHIFT_CAEP_CEQ_ALM_OVF_INT_ST_S) == 1) { > + dev_warn(dev, "CEQ[%d] almost overflow!\n", i); > + int_work++; > + > + /* Set mask */ > + cemask_val = roce_read(hr_dev, > + ROCEE_CAEP_CE_IRQ_MASK_0_REG + > + i * CEQ_REG_OFFSET); > + roce_set_bit(cemask_val, > + ROCEE_CAEP_CE_IRQ_MASK_CAEP_CEQ_ALM_OVF_MASK_S, > + HNS_ROCE_INT_MASK_ENABLE); > + roce_write(hr_dev, ROCEE_CAEP_CE_IRQ_MASK_0_REG + > + i * CEQ_REG_OFFSET, cemask_val); > + > + /* Clear int state(INT_WC : write 1 clear) */ > + cealmovf_val = roce_read(hr_dev, > + ROCEE_CAEP_CEQ_ALM_OVF_0_REG + > + i * CEQ_REG_OFFSET); > + roce_set_bit(cealmovf_val, > + ROCEE_CAEP_CEQ_ALM_OVF_CAEP_CEQ_ALM_OVF_S, > + 1); > + roce_write(hr_dev, ROCEE_CAEP_CEQ_ALM_OVF_0_REG + > + i * CEQ_REG_OFFSET, cealmovf_val); > + > + /* Clear mask */ > + cemask_val = roce_read(hr_dev, > + ROCEE_CAEP_CE_IRQ_MASK_0_REG + > + i * CEQ_REG_OFFSET); > + roce_set_bit(cemask_val, > + ROCEE_CAEP_CE_IRQ_MASK_CAEP_CEQ_ALM_OVF_MASK_S, > + HNS_ROCE_INT_MASK_DISABLE); > + roce_write(hr_dev, ROCEE_CAEP_CE_IRQ_MASK_0_REG + > + i * CEQ_REG_OFFSET, cemask_val); > + } > + } > + > + /* ECC multi-bit error alarm */ > + dev_warn(dev, "ECC UCERR ALARM: 0x%x, 0x%x, 0x%x\n", > + roce_read(hr_dev, ROCEE_ECC_UCERR_ALM0_REG), > + roce_read(hr_dev, ROCEE_ECC_UCERR_ALM1_REG), > + roce_read(hr_dev, ROCEE_ECC_UCERR_ALM2_REG)); > + > + dev_warn(dev, "ECC CERR ALARM: 0x%x, 0x%x, 0x%x\n", > + roce_read(hr_dev, ROCEE_ECC_CERR_ALM0_REG), > + roce_read(hr_dev, ROCEE_ECC_CERR_ALM1_REG), > + roce_read(hr_dev, ROCEE_ECC_CERR_ALM2_REG)); > + > + return IRQ_RETVAL(int_work); > +} > + > +static void hns_roce_v1_int_mask_enable(struct hns_roce_dev *hr_dev) > +{ > + u32 aemask_val; > + int masken = 0; > + int i; > + > + /* AEQ INT */ > + aemask_val = roce_read(hr_dev, ROCEE_CAEP_AE_MASK_REG); > + roce_set_bit(aemask_val, ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S, > + masken); > + roce_set_bit(aemask_val, ROCEE_CAEP_AE_MASK_CAEP_AE_IRQ_MASK_S, masken); > + roce_write(hr_dev, ROCEE_CAEP_AE_MASK_REG, aemask_val); > + > + /* CEQ INT */ > + for (i = 0; i < hr_dev->caps.num_comp_vectors; i++) { > + /* IRQ mask */ > + roce_write(hr_dev, ROCEE_CAEP_CE_IRQ_MASK_0_REG + > + i * CEQ_REG_OFFSET, masken); > + } > +} > + > +static void hns_roce_v1_free_eq(struct hns_roce_dev *hr_dev, > + struct hns_roce_eq *eq) > +{ > + int npages = (PAGE_ALIGN(eq->eqe_size * eq->entries) + > + HNS_ROCE_BA_SIZE - 1) / HNS_ROCE_BA_SIZE; > + int i; > + > + if (!eq->buf_list) > + return; > + > + for (i = 0; i < npages; ++i) > + dma_free_coherent(&hr_dev->pdev->dev, HNS_ROCE_BA_SIZE, > + eq->buf_list[i].buf, eq->buf_list[i].map); > + > + kfree(eq->buf_list); > +} > + > +static void hns_roce_v1_enable_eq(struct hns_roce_dev *hr_dev, int eq_num, > + int enable_flag) > +{ > + void __iomem *eqc = hr_dev->eq_table.eqc_base[eq_num]; > + u32 val; > + > + val = readl(eqc); > + > + if (enable_flag) > + roce_set_field(val, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S, > + HNS_ROCE_EQ_STAT_VALID); > + else > + roce_set_field(val, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S, > + HNS_ROCE_EQ_STAT_INVALID); > + writel(val, eqc); > +} > + > +static int hns_roce_v1_create_eq(struct hns_roce_dev *hr_dev, > + struct hns_roce_eq *eq) > +{ > + void __iomem *eqc = hr_dev->eq_table.eqc_base[eq->eqn]; > + struct device *dev = &hr_dev->pdev->dev; > + dma_addr_t tmp_dma_addr; > + u32 eqconsindx_val = 0; > + u32 eqcuridx_val = 0; > + u32 eqshift_val = 0; > + int num_bas; > + int ret; > + int i; > + > + num_bas = (PAGE_ALIGN(eq->entries * eq->eqe_size) + > + HNS_ROCE_BA_SIZE - 1) / HNS_ROCE_BA_SIZE; > + > + if ((eq->entries * eq->eqe_size) > HNS_ROCE_BA_SIZE) { > + dev_err(dev, "[error]eq buf %d gt ba size(%d) need bas=%d\n", > + (eq->entries * eq->eqe_size), HNS_ROCE_BA_SIZE, > + num_bas); > + return -EINVAL; > + } > + > + eq->buf_list = kcalloc(num_bas, sizeof(*eq->buf_list), GFP_KERNEL); > + if (!eq->buf_list) > + return -ENOMEM; > + > + for (i = 0; i < num_bas; ++i) { > + eq->buf_list[i].buf = dma_alloc_coherent(dev, HNS_ROCE_BA_SIZE, > + &tmp_dma_addr, > + GFP_KERNEL); > + if (!eq->buf_list[i].buf) { > + ret = -ENOMEM; > + goto err_out_free_pages; > + } > + > + eq->buf_list[i].map = tmp_dma_addr; > + memset(eq->buf_list[i].buf, 0, HNS_ROCE_BA_SIZE); > + } > + eq->cons_index = 0; > + roce_set_field(eqshift_val, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S, > + HNS_ROCE_EQ_STAT_INVALID); > + roce_set_field(eqshift_val, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_M, > + ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_S, > + eq->log_entries); > + writel(eqshift_val, eqc); > + > + /* Configure eq extended address 12~44bit */ > + writel((u32)(eq->buf_list[0].map >> 12), eqc + 4); > + > + /* > + * Configure eq extended address 45~49 bit. > + * 44 = 32 + 12, When evaluating addr to hardware, shift 12 because of > + * using 4K page, and shift more 32 because of > + * caculating the high 32 bit value evaluated to hardware. > + */ > + roce_set_field(eqcuridx_val, ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_M, > + ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_S, > + eq->buf_list[0].map >> 44); > + roce_set_field(eqcuridx_val, > + ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_M, > + ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_S, 0); > + writel(eqcuridx_val, eqc + 8); > + > + /* Configure eq consumer index */ > + roce_set_field(eqconsindx_val, > + ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_M, > + ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_S, 0); > + writel(eqconsindx_val, eqc + 0xc); > + > + return 0; > + > +err_out_free_pages: > + for (i -= 1; i >= 0; i--) > + dma_free_coherent(dev, HNS_ROCE_BA_SIZE, eq->buf_list[i].buf, > + eq->buf_list[i].map); > + > + kfree(eq->buf_list); > + return ret; > +} > + > +static int hns_roce_v1_init_eq_table(struct hns_roce_dev *hr_dev) > +{ > + struct hns_roce_eq_table *eq_table = &hr_dev->eq_table; > + struct device *dev = &hr_dev->pdev->dev; > + struct hns_roce_eq *eq; > + int irq_num; > + int eq_num; > + int ret; > + int i, j; > + > + eq_num = hr_dev->caps.num_comp_vectors + hr_dev->caps.num_aeq_vectors; > + irq_num = eq_num + hr_dev->caps.num_other_vectors; > + > + eq_table->eq = kcalloc(eq_num, sizeof(*eq_table->eq), GFP_KERNEL); > + if (!eq_table->eq) > + return -ENOMEM; > + > + eq_table->eqc_base = kcalloc(eq_num, sizeof(*eq_table->eqc_base), > + GFP_KERNEL); > + if (!eq_table->eqc_base) { > + ret = -ENOMEM; > + goto err_eqc_base_alloc_fail; > + } > + > + for (i = 0; i < eq_num; i++) { > + eq = &eq_table->eq[i]; > + eq->hr_dev = hr_dev; > + eq->eqn = i; > + eq->irq = hr_dev->irq[i]; > + eq->log_page_size = PAGE_SHIFT; > + > + if (i < hr_dev->caps.num_comp_vectors) { > + /* CEQ */ > + eq_table->eqc_base[i] = hr_dev->reg_base + > + ROCEE_CAEP_CEQC_SHIFT_0_REG + > + CEQ_REG_OFFSET * i; > + eq->type_flag = HNS_ROCE_CEQ; > + eq->doorbell = hr_dev->reg_base + > + ROCEE_CAEP_CEQC_CONS_IDX_0_REG + > + CEQ_REG_OFFSET * i; > + eq->entries = hr_dev->caps.ceqe_depth; > + eq->log_entries = ilog2(eq->entries); > + eq->eqe_size = HNS_ROCE_CEQ_ENTRY_SIZE; > + } else { > + /* AEQ */ > + eq_table->eqc_base[i] = hr_dev->reg_base + > + ROCEE_CAEP_AEQC_AEQE_SHIFT_REG; > + eq->type_flag = HNS_ROCE_AEQ; > + eq->doorbell = hr_dev->reg_base + > + ROCEE_CAEP_AEQE_CONS_IDX_REG; > + eq->entries = hr_dev->caps.aeqe_depth; > + eq->log_entries = ilog2(eq->entries); > + eq->eqe_size = HNS_ROCE_AEQ_ENTRY_SIZE; > + } > + } > + > + /* Disable irq */ > + hns_roce_v1_int_mask_enable(hr_dev); > + > + /* Configure ce int interval */ > + roce_write(hr_dev, ROCEE_CAEP_CE_INTERVAL_CFG_REG, > + HNS_ROCE_CEQ_DEFAULT_INTERVAL); > + > + /* Configure ce int burst num */ > + roce_write(hr_dev, ROCEE_CAEP_CE_BURST_NUM_CFG_REG, > + HNS_ROCE_CEQ_DEFAULT_BURST_NUM); > + > + for (i = 0; i < eq_num; i++) { > + ret = hns_roce_v1_create_eq(hr_dev, &eq_table->eq[i]); > + if (ret) { > + dev_err(dev, "eq create failed\n"); > + goto err_create_eq_fail; > + } > + } > + > + for (j = 0; j < irq_num; j++) { > + if (j < eq_num) > + ret = request_irq(hr_dev->irq[j], > + hns_roce_v1_msix_interrupt_eq, 0, > + hr_dev->irq_names[j], > + &eq_table->eq[j]); > + else > + ret = request_irq(hr_dev->irq[j], > + hns_roce_v1_msix_interrupt_abn, 0, > + hr_dev->irq_names[j], hr_dev); > + > + if (ret) { > + dev_err(dev, "request irq error!\n"); > + goto err_request_irq_fail; > + } > + } > + > + for (i = 0; i < eq_num; i++) > + hns_roce_v1_enable_eq(hr_dev, i, EQ_ENABLE); > + > + return 0; > + > +err_request_irq_fail: > + for (j -= 1; j >= 0; j--) > + free_irq(hr_dev->irq[j], &eq_table->eq[j]); > + > +err_create_eq_fail: > + for (i -= 1; i >= 0; i--) > + hns_roce_v1_free_eq(hr_dev, &eq_table->eq[i]); > + > + kfree(eq_table->eqc_base); > + > +err_eqc_base_alloc_fail: > + kfree(eq_table->eq); > + > + return ret; > +} > + > +static void hns_roce_v1_cleanup_eq_table(struct hns_roce_dev *hr_dev) > +{ > + struct hns_roce_eq_table *eq_table = &hr_dev->eq_table; > + int irq_num; > + int eq_num; > + int i; > + > + eq_num = hr_dev->caps.num_comp_vectors + hr_dev->caps.num_aeq_vectors; > + irq_num = eq_num + hr_dev->caps.num_other_vectors; > + for (i = 0; i < eq_num; i++) { > + /* Disable EQ */ > + hns_roce_v1_enable_eq(hr_dev, i, EQ_DISABLE); > + > + free_irq(hr_dev->irq[i], &eq_table->eq[i]); > + > + hns_roce_v1_free_eq(hr_dev, &eq_table->eq[i]); > + } > + for (i = eq_num; i < irq_num; i++) > + free_irq(hr_dev->irq[i], hr_dev); > + > + kfree(eq_table->eqc_base); > + kfree(eq_table->eq); > +} > + > static const struct hns_roce_hw hns_roce_hw_v1 = { > .reset = hns_roce_v1_reset, > .hw_profile = hns_roce_v1_profile, > @@ -3983,6 +4703,8 @@ static int hns_roce_v1_destroy_cq(struct ib_cq *ibcq) > .poll_cq = hns_roce_v1_poll_cq, > .dereg_mr = hns_roce_v1_dereg_mr, > .destroy_cq = hns_roce_v1_destroy_cq, > + .init_eq = hns_roce_v1_init_eq_table, > + .cleanup_eq = hns_roce_v1_cleanup_eq_table, > }; > > static const struct of_device_id hns_roce_of_match[] = { > @@ -4132,14 +4854,14 @@ static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev) > /* read the interrupt names from the DT or ACPI */ > ret = device_property_read_string_array(dev, "interrupt-names", > hr_dev->irq_names, > - HNS_ROCE_MAX_IRQ_NUM); > + HNS_ROCE_V1_MAX_IRQ_NUM); > if (ret < 0) { > dev_err(dev, "couldn't get interrupt names from DT or ACPI!\n"); > return ret; > } > > /* fetch the interrupt numbers */ > - for (i = 0; i < HNS_ROCE_MAX_IRQ_NUM; i++) { > + for (i = 0; i < HNS_ROCE_V1_MAX_IRQ_NUM; i++) { > hr_dev->irq[i] = platform_get_irq(hr_dev->pdev, i); > if (hr_dev->irq[i] <= 0) { > dev_err(dev, "platform get of irq[=%d] failed!\n", i); > diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.h b/drivers/infiniband/hw/hns/hns_roce_hw_v1.h > index 21a07ef..b44ddd2 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.h > +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.h > @@ -60,8 +60,13 @@ > #define HNS_ROCE_V1_GID_NUM 16 > #define HNS_ROCE_V1_RESV_QP 8 > > -#define HNS_ROCE_V1_NUM_COMP_EQE 0x8000 > -#define HNS_ROCE_V1_NUM_ASYNC_EQE 0x400 > +#define HNS_ROCE_V1_MAX_IRQ_NUM 34 > +#define HNS_ROCE_V1_COMP_VEC_NUM 32 > +#define HNS_ROCE_V1_AEQE_VEC_NUM 1 > +#define HNS_ROCE_V1_ABNORMAL_VEC_NUM 1 > + > +#define HNS_ROCE_V1_COMP_EQE_NUM 0x8000 > +#define HNS_ROCE_V1_ASYNC_EQE_NUM 0x400 > > #define HNS_ROCE_V1_QPC_ENTRY_SIZE 256 > #define HNS_ROCE_V1_IRRL_ENTRY_SIZE 8 > @@ -159,6 +164,41 @@ > #define SDB_INV_CNT_OFFSET 8 > #define SDB_ST_CMP_VAL 8 > > +#define HNS_ROCE_CEQ_DEFAULT_INTERVAL 0x10 > +#define HNS_ROCE_CEQ_DEFAULT_BURST_NUM 0x10 > + > +#define HNS_ROCE_INT_MASK_DISABLE 0 > +#define HNS_ROCE_INT_MASK_ENABLE 1 > + > +#define CEQ_REG_OFFSET 0x18 > + > +#define HNS_ROCE_CEQE_CEQE_COMP_OWNER_S 0 > + > +#define HNS_ROCE_V1_CONS_IDX_M GENMASK(15, 0) > + > +#define HNS_ROCE_CEQE_CEQE_COMP_CQN_S 16 > +#define HNS_ROCE_CEQE_CEQE_COMP_CQN_M GENMASK(31, 16) > + > +#define HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S 16 > +#define HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M GENMASK(23, 16) > + > +#define HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_S 24 > +#define HNS_ROCE_AEQE_U32_4_EVENT_SUB_TYPE_M GENMASK(30, 24) > + > +#define HNS_ROCE_AEQE_U32_4_OWNER_S 31 > + > +#define HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_S 0 > +#define HNS_ROCE_AEQE_EVENT_QP_EVENT_QP_QPN_M GENMASK(23, 0) > + > +#define HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_S 25 > +#define HNS_ROCE_AEQE_EVENT_QP_EVENT_PORT_NUM_M GENMASK(27, 25) > + > +#define HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_S 0 > +#define HNS_ROCE_AEQE_EVENT_CQ_EVENT_CQ_CQN_M GENMASK(15, 0) > + > +#define HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_S 0 > +#define HNS_ROCE_AEQE_EVENT_CE_EVENT_CEQE_CEQN_M GENMASK(4, 0) > + > struct hns_roce_cq_context { > u32 cqc_byte_4; > u32 cq_bt_l; > diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c > index cf02ac2..aa0c242 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_main.c > +++ b/drivers/infiniband/hw/hns/hns_roce_main.c > @@ -748,12 +748,10 @@ int hns_roce_init(struct hns_roce_dev *hr_dev) > goto error_failed_cmd_init; > } > > - if (hr_dev->cmd_mod) { > - ret = hns_roce_init_eq_table(hr_dev); > - if (ret) { > - dev_err(dev, "eq init failed!\n"); > - goto error_failed_eq_table; > - } > + ret = hr_dev->hw->init_eq(hr_dev); > + if (ret) { > + dev_err(dev, "eq init failed!\n"); > + goto error_failed_eq_table; > } > > if (hr_dev->cmd_mod) { > @@ -805,8 +803,7 @@ int hns_roce_init(struct hns_roce_dev *hr_dev) > hns_roce_cmd_use_polling(hr_dev); > > error_failed_use_event: > - if (hr_dev->cmd_mod) > - hns_roce_cleanup_eq_table(hr_dev); > + hr_dev->hw->cleanup_eq(hr_dev); > > error_failed_eq_table: > hns_roce_cmd_cleanup(hr_dev); > @@ -837,8 +834,7 @@ void hns_roce_exit(struct hns_roce_dev *hr_dev) > if (hr_dev->cmd_mod) > hns_roce_cmd_use_polling(hr_dev); > > - if (hr_dev->cmd_mod) > - hns_roce_cleanup_eq_table(hr_dev); > + hr_dev->hw->cleanup_eq(hr_dev); > hns_roce_cmd_cleanup(hr_dev); > if (hr_dev->hw->cmq_exit) > hr_dev->hw->cmq_exit(hr_dev); > diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c > index 49586ec..69e2584 100644 > --- a/drivers/infiniband/hw/hns/hns_roce_qp.c > +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c > @@ -65,6 +65,7 @@ void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type) > if (atomic_dec_and_test(&qp->refcount)) > complete(&qp->free); > } > +EXPORT_SYMBOL_GPL(hns_roce_qp_event); > > static void hns_roce_ib_qp_event(struct hns_roce_qp *hr_qp, > enum hns_roce_event type) > -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html