Commit bfcc681b authored by Shaobo Xu's avatar Shaobo Xu Committed by Doug Ledford

IB/hns: Fix the bug when free mr

If the resources of mr are freed while executing the user case, hardware
can not been notified in hip06 SoC. Then hardware will hold on when it
reads the payload by the PA which has been released.

In order to slove this problem, RoCE driver creates 8 reserved loopback
QPs to ensure zero wqe when free mr. When the mac address is reset, in
order to avoid loopback failure, we need to release the reserved loopback
QPs and recreate them.
Signed-off-by: default avatarShaobo Xu <xushaobo2@huawei.com>
Reviewed-by: default avatarWei Hu (Xavier) <xavier.huwei@huawei.com>
Signed-off-by: default avatarSalil Mehta <salil.mehta@huawei.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent d838c481
...@@ -58,11 +58,6 @@ enum { ...@@ -58,11 +58,6 @@ enum {
HNS_ROCE_CMD_QUERY_QP = 0x22, HNS_ROCE_CMD_QUERY_QP = 0x22,
}; };
struct hns_roce_cmd_mailbox {
void *buf;
dma_addr_t dma;
};
int hns_roce_cmd_mbox(struct hns_roce_dev *hr_dev, u64 in_param, u64 out_param, int hns_roce_cmd_mbox(struct hns_roce_dev *hr_dev, u64 in_param, u64 out_param,
unsigned long in_modifier, u8 op_modifier, u16 op, unsigned long in_modifier, u8 op_modifier, u16 op,
unsigned long timeout); unsigned long timeout);
......
...@@ -388,6 +388,11 @@ struct hns_roce_cmdq { ...@@ -388,6 +388,11 @@ struct hns_roce_cmdq {
u8 toggle; u8 toggle;
}; };
struct hns_roce_cmd_mailbox {
void *buf;
dma_addr_t dma;
};
struct hns_roce_dev; struct hns_roce_dev;
struct hns_roce_qp { struct hns_roce_qp {
...@@ -522,6 +527,7 @@ struct hns_roce_hw { ...@@ -522,6 +527,7 @@ struct hns_roce_hw {
struct ib_recv_wr **bad_recv_wr); struct ib_recv_wr **bad_recv_wr);
int (*req_notify_cq)(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); int (*req_notify_cq)(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
int (*poll_cq)(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); int (*poll_cq)(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
int (*dereg_mr)(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr);
void *priv; void *priv;
}; };
...@@ -688,6 +694,10 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -688,6 +694,10 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int access_flags, u64 virt_addr, int access_flags,
struct ib_udata *udata); struct ib_udata *udata);
int hns_roce_dereg_mr(struct ib_mr *ibmr); int hns_roce_dereg_mr(struct ib_mr *ibmr);
int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
struct hns_roce_cmd_mailbox *mailbox,
unsigned long mpt_index);
unsigned long key_to_hw_index(u32 key);
void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size, void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size,
struct hns_roce_buf *buf); struct hns_roce_buf *buf);
......
This diff is collapsed.
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#define HNS_ROCE_V1_PHY_UAR_NUM 8 #define HNS_ROCE_V1_PHY_UAR_NUM 8
#define HNS_ROCE_V1_GID_NUM 16 #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_COMP_EQE 0x8000
#define HNS_ROCE_V1_NUM_ASYNC_EQE 0x400 #define HNS_ROCE_V1_NUM_ASYNC_EQE 0x400
...@@ -107,6 +108,10 @@ ...@@ -107,6 +108,10 @@
#define HNS_ROCE_V1_DB_STAGE2 2 #define HNS_ROCE_V1_DB_STAGE2 2
#define HNS_ROCE_V1_CHECK_DB_TIMEOUT_MSECS 10000 #define HNS_ROCE_V1_CHECK_DB_TIMEOUT_MSECS 10000
#define HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS 20 #define HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS 20
#define HNS_ROCE_V1_FREE_MR_TIMEOUT_MSECS 50000
#define HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS 10000
#define HNS_ROCE_V1_FREE_MR_WAIT_VALUE 5
#define HNS_ROCE_V1_RECREATE_LP_QP_WAIT_VALUE 20
#define HNS_ROCE_BT_RSV_BUF_SIZE (1 << 17) #define HNS_ROCE_BT_RSV_BUF_SIZE (1 << 17)
...@@ -969,6 +974,10 @@ struct hns_roce_sq_db { ...@@ -969,6 +974,10 @@ struct hns_roce_sq_db {
#define SQ_DOORBELL_U32_4_SQ_HEAD_M \ #define SQ_DOORBELL_U32_4_SQ_HEAD_M \
(((1UL << 15) - 1) << SQ_DOORBELL_U32_4_SQ_HEAD_S) (((1UL << 15) - 1) << SQ_DOORBELL_U32_4_SQ_HEAD_S)
#define SQ_DOORBELL_U32_4_SL_S 16
#define SQ_DOORBELL_U32_4_SL_M \
(((1UL << 2) - 1) << SQ_DOORBELL_U32_4_SL_S)
#define SQ_DOORBELL_U32_4_PORT_S 18 #define SQ_DOORBELL_U32_4_PORT_S 18
#define SQ_DOORBELL_U32_4_PORT_M (((1UL << 3) - 1) << SQ_DOORBELL_U32_4_PORT_S) #define SQ_DOORBELL_U32_4_PORT_M (((1UL << 3) - 1) << SQ_DOORBELL_U32_4_PORT_S)
...@@ -1015,14 +1024,39 @@ struct hns_roce_des_qp { ...@@ -1015,14 +1024,39 @@ struct hns_roce_des_qp {
int requeue_flag; int requeue_flag;
}; };
struct hns_roce_mr_free_work {
struct work_struct work;
struct ib_device *ib_dev;
struct completion *comp;
int comp_flag;
void *mr;
};
struct hns_roce_recreate_lp_qp_work {
struct work_struct work;
struct ib_device *ib_dev;
struct completion *comp;
int comp_flag;
};
struct hns_roce_free_mr {
struct workqueue_struct *free_mr_wq;
struct hns_roce_qp *mr_free_qp[HNS_ROCE_V1_RESV_QP];
struct hns_roce_cq *mr_free_cq;
struct hns_roce_pd *mr_free_pd;
};
struct hns_roce_v1_priv { struct hns_roce_v1_priv {
struct hns_roce_db_table db_table; struct hns_roce_db_table db_table;
struct hns_roce_raq_table raq_table; struct hns_roce_raq_table raq_table;
struct hns_roce_bt_table bt_table; struct hns_roce_bt_table bt_table;
struct hns_roce_tptr_table tptr_table; struct hns_roce_tptr_table tptr_table;
struct hns_roce_des_qp des_qp; struct hns_roce_des_qp des_qp;
struct hns_roce_free_mr free_mr;
}; };
int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset); int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset);
int hns_roce_v1_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
int hns_roce_v1_destroy_qp(struct ib_qp *ibqp);
#endif #endif
...@@ -129,7 +129,6 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port, ...@@ -129,7 +129,6 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
{ {
struct device *dev = &hr_dev->pdev->dev; struct device *dev = &hr_dev->pdev->dev;
struct net_device *netdev; struct net_device *netdev;
unsigned long flags;
netdev = hr_dev->iboe.netdevs[port]; netdev = hr_dev->iboe.netdevs[port];
if (!netdev) { if (!netdev) {
...@@ -137,7 +136,7 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port, ...@@ -137,7 +136,7 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
return -ENODEV; return -ENODEV;
} }
spin_lock_irqsave(&hr_dev->iboe.lock, flags); spin_lock_bh(&hr_dev->iboe.lock);
switch (event) { switch (event) {
case NETDEV_UP: case NETDEV_UP:
...@@ -156,7 +155,7 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port, ...@@ -156,7 +155,7 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
break; break;
} }
spin_unlock_irqrestore(&hr_dev->iboe.lock, flags); spin_unlock_bh(&hr_dev->iboe.lock);
return 0; return 0;
} }
......
...@@ -42,7 +42,7 @@ static u32 hw_index_to_key(unsigned long ind) ...@@ -42,7 +42,7 @@ static u32 hw_index_to_key(unsigned long ind)
return (u32)(ind >> 24) | (ind << 8); return (u32)(ind >> 24) | (ind << 8);
} }
static unsigned long key_to_hw_index(u32 key) unsigned long key_to_hw_index(u32 key)
{ {
return (key << 24) | (key >> 8); return (key << 24) | (key >> 8);
} }
...@@ -56,7 +56,7 @@ static int hns_roce_sw2hw_mpt(struct hns_roce_dev *hr_dev, ...@@ -56,7 +56,7 @@ static int hns_roce_sw2hw_mpt(struct hns_roce_dev *hr_dev,
HNS_ROCE_CMD_TIMEOUT_MSECS); HNS_ROCE_CMD_TIMEOUT_MSECS);
} }
static int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev, int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
struct hns_roce_cmd_mailbox *mailbox, struct hns_roce_cmd_mailbox *mailbox,
unsigned long mpt_index) unsigned long mpt_index)
{ {
...@@ -607,13 +607,20 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -607,13 +607,20 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
int hns_roce_dereg_mr(struct ib_mr *ibmr) int hns_roce_dereg_mr(struct ib_mr *ibmr)
{ {
struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);
struct hns_roce_mr *mr = to_hr_mr(ibmr); struct hns_roce_mr *mr = to_hr_mr(ibmr);
int ret = 0;
hns_roce_mr_free(to_hr_dev(ibmr->device), mr); if (hr_dev->hw->dereg_mr) {
if (mr->umem) ret = hr_dev->hw->dereg_mr(hr_dev, mr);
ib_umem_release(mr->umem); } else {
hns_roce_mr_free(hr_dev, mr);
kfree(mr); if (mr->umem)
ib_umem_release(mr->umem);
return 0; kfree(mr);
}
return ret;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment