Commit a680f2f3 authored by Wei Hu(Xavier)'s avatar Wei Hu(Xavier) Committed by Doug Ledford

RDMA/hns: Add mailbox's implementation for hip08 RoCE driver

In hip08 SoC, the hardware implementation of mailbox command
has changed with hip06 SoC. As a result, it adjusts the
architecture of the command code and implements the interfaces
of mailbox for hip08 SoC.
Signed-off-by: default avatarLijun Ou <oulijun@huawei.com>
Signed-off-by: default avatarShaobo Xu <xushaobo2@huawei.com>
Signed-off-by: default avatarWei Hu (Xavier) <xavier.huwei@huawei.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent cfc85f3e
...@@ -38,69 +38,7 @@ ...@@ -38,69 +38,7 @@
#define CMD_POLL_TOKEN 0xffff #define CMD_POLL_TOKEN 0xffff
#define CMD_MAX_NUM 32 #define CMD_MAX_NUM 32
#define STATUS_MASK 0xff
#define CMD_TOKEN_MASK 0x1f #define CMD_TOKEN_MASK 0x1f
#define GO_BIT_TIMEOUT_MSECS 10000
enum {
HCR_TOKEN_OFFSET = 0x14,
HCR_STATUS_OFFSET = 0x18,
HCR_GO_BIT = 15,
};
static int cmd_pending(struct hns_roce_dev *hr_dev)
{
u32 status = readl(hr_dev->cmd.hcr + HCR_TOKEN_OFFSET);
return (!!(status & (1 << HCR_GO_BIT)));
}
/* this function should be serialized with "hcr_mutex" */
static int __hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev,
u64 in_param, u64 out_param,
u32 in_modifier, u8 op_modifier, u16 op,
u16 token, int event)
{
struct hns_roce_cmdq *cmd = &hr_dev->cmd;
struct device *dev = &hr_dev->pdev->dev;
u32 __iomem *hcr = (u32 *)cmd->hcr;
int ret = -EAGAIN;
unsigned long end;
u32 val = 0;
end = msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS) + jiffies;
while (cmd_pending(hr_dev)) {
if (time_after(jiffies, end)) {
dev_dbg(dev, "jiffies=%d end=%d\n", (int)jiffies,
(int)end);
goto out;
}
cond_resched();
}
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_M, ROCEE_MB6_ROCEE_MB_CMD_S,
op);
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_MDF_M,
ROCEE_MB6_ROCEE_MB_CMD_MDF_S, op_modifier);
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_EVENT_S, event);
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_HW_RUN_S, 1);
roce_set_field(val, ROCEE_MB6_ROCEE_MB_TOKEN_M,
ROCEE_MB6_ROCEE_MB_TOKEN_S, token);
__raw_writeq(cpu_to_le64(in_param), hcr + 0);
__raw_writeq(cpu_to_le64(out_param), hcr + 2);
__raw_writel(cpu_to_le32(in_modifier), hcr + 4);
/* Memory barrier */
wmb();
__raw_writel(cpu_to_le32(val), hcr + 5);
mmiowb();
ret = 0;
out:
return ret;
}
static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev, u64 in_param, static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev, u64 in_param,
u64 out_param, u32 in_modifier, u64 out_param, u32 in_modifier,
...@@ -108,12 +46,11 @@ static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev, u64 in_param, ...@@ -108,12 +46,11 @@ static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev, u64 in_param,
int event) int event)
{ {
struct hns_roce_cmdq *cmd = &hr_dev->cmd; struct hns_roce_cmdq *cmd = &hr_dev->cmd;
int ret = -EAGAIN; int ret;
mutex_lock(&cmd->hcr_mutex); mutex_lock(&cmd->hcr_mutex);
ret = __hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param, ret = hr_dev->hw->post_mbox(hr_dev, in_param, out_param, in_modifier,
in_modifier, op_modifier, op, token, op_modifier, op, token, event);
event);
mutex_unlock(&cmd->hcr_mutex); mutex_unlock(&cmd->hcr_mutex);
return ret; return ret;
...@@ -126,9 +63,6 @@ static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param, ...@@ -126,9 +63,6 @@ static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
unsigned long timeout) unsigned long timeout)
{ {
struct device *dev = hr_dev->dev; struct device *dev = hr_dev->dev;
u8 __iomem *hcr = hr_dev->cmd.hcr;
unsigned long end = 0;
u32 status = 0;
int ret; int ret;
ret = hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param, ret = hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param,
...@@ -136,29 +70,10 @@ static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param, ...@@ -136,29 +70,10 @@ static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
CMD_POLL_TOKEN, 0); CMD_POLL_TOKEN, 0);
if (ret) { if (ret) {
dev_err(dev, "[cmd_poll]hns_roce_cmd_mbox_post_hw failed\n"); dev_err(dev, "[cmd_poll]hns_roce_cmd_mbox_post_hw failed\n");
goto out; return ret;
}
end = msecs_to_jiffies(timeout) + jiffies;
while (cmd_pending(hr_dev) && time_before(jiffies, end))
cond_resched();
if (cmd_pending(hr_dev)) {
dev_err(dev, "[cmd_poll]hw run cmd TIMEDOUT!\n");
ret = -ETIMEDOUT;
goto out;
} }
status = le32_to_cpu((__force __be32) return hr_dev->hw->chk_mbox(hr_dev, timeout);
__raw_readl(hcr + HCR_STATUS_OFFSET));
if ((status & STATUS_MASK) != 0x1) {
dev_err(dev, "mailbox status 0x%x!\n", status);
ret = -EBUSY;
goto out;
}
out:
return ret;
} }
static int hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param, static int hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
...@@ -198,7 +113,7 @@ static int __hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev, u64 in_param, ...@@ -198,7 +113,7 @@ static int __hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev, u64 in_param,
struct hns_roce_cmdq *cmd = &hr_dev->cmd; struct hns_roce_cmdq *cmd = &hr_dev->cmd;
struct hns_roce_cmd_context *context; struct hns_roce_cmd_context *context;
struct device *dev = hr_dev->dev; struct device *dev = hr_dev->dev;
int ret = 0; int ret;
spin_lock(&cmd->context_lock); spin_lock(&cmd->context_lock);
WARN_ON(cmd->free_head < 0); WARN_ON(cmd->free_head < 0);
...@@ -280,7 +195,6 @@ int hns_roce_cmd_init(struct hns_roce_dev *hr_dev) ...@@ -280,7 +195,6 @@ int hns_roce_cmd_init(struct hns_roce_dev *hr_dev)
hr_dev->cmd.use_events = 0; hr_dev->cmd.use_events = 0;
hr_dev->cmd.toggle = 1; hr_dev->cmd.toggle = 1;
hr_dev->cmd.max_cmds = CMD_MAX_NUM; hr_dev->cmd.max_cmds = CMD_MAX_NUM;
hr_dev->cmd.hcr = hr_dev->reg_base + ROCEE_MB1_REG;
hr_dev->cmd.pool = dma_pool_create("hns_roce_cmd", dev, hr_dev->cmd.pool = dma_pool_create("hns_roce_cmd", dev,
HNS_ROCE_MAILBOX_SIZE, HNS_ROCE_MAILBOX_SIZE,
HNS_ROCE_MAILBOX_SIZE, 0); HNS_ROCE_MAILBOX_SIZE, 0);
......
...@@ -341,6 +341,7 @@ ...@@ -341,6 +341,7 @@
#define ROCEE_BT_CMD_L_REG 0x200 #define ROCEE_BT_CMD_L_REG 0x200
#define ROCEE_MB1_REG 0x210 #define ROCEE_MB1_REG 0x210
#define ROCEE_MB6_REG 0x224
#define ROCEE_DB_SQ_L_0_REG 0x230 #define ROCEE_DB_SQ_L_0_REG 0x230
#define ROCEE_DB_OTHERS_L_0_REG 0x238 #define ROCEE_DB_OTHERS_L_0_REG 0x238
#define ROCEE_QP1C_CFG0_0_REG 0x270 #define ROCEE_QP1C_CFG0_0_REG 0x270
......
...@@ -367,7 +367,6 @@ struct hns_roce_cmd_context { ...@@ -367,7 +367,6 @@ struct hns_roce_cmd_context {
struct hns_roce_cmdq { struct hns_roce_cmdq {
struct dma_pool *pool; struct dma_pool *pool;
u8 __iomem *hcr;
struct mutex hcr_mutex; struct mutex hcr_mutex;
struct semaphore poll_sem; struct semaphore poll_sem;
/* /*
...@@ -517,6 +516,10 @@ struct hns_roce_hw { ...@@ -517,6 +516,10 @@ struct hns_roce_hw {
int (*hw_profile)(struct hns_roce_dev *hr_dev); int (*hw_profile)(struct hns_roce_dev *hr_dev);
int (*hw_init)(struct hns_roce_dev *hr_dev); int (*hw_init)(struct hns_roce_dev *hr_dev);
void (*hw_exit)(struct hns_roce_dev *hr_dev); void (*hw_exit)(struct hns_roce_dev *hr_dev);
int (*post_mbox)(struct hns_roce_dev *hr_dev, u64 in_param,
u64 out_param, u32 in_modifier, u8 op_modifier, u16 op,
u16 token, int event);
int (*chk_mbox)(struct hns_roce_dev *hr_dev, unsigned long timeout);
void (*set_gid)(struct hns_roce_dev *hr_dev, u8 port, int gid_index, void (*set_gid)(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
union ib_gid *gid); union ib_gid *gid);
void (*set_mac)(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr); void (*set_mac)(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr);
......
...@@ -1619,6 +1619,79 @@ void hns_roce_v1_exit(struct hns_roce_dev *hr_dev) ...@@ -1619,6 +1619,79 @@ void hns_roce_v1_exit(struct hns_roce_dev *hr_dev)
hns_roce_db_free(hr_dev); hns_roce_db_free(hr_dev);
} }
static int hns_roce_v1_cmd_pending(struct hns_roce_dev *hr_dev)
{
u32 status = readl(hr_dev->reg_base + ROCEE_MB6_REG);
return (!!(status & (1 << HCR_GO_BIT)));
}
int hns_roce_v1_post_mbox(struct hns_roce_dev *hr_dev, u64 in_param,
u64 out_param, u32 in_modifier, u8 op_modifier,
u16 op, u16 token, int event)
{
u32 *hcr = (u32 *)(hr_dev->reg_base + ROCEE_MB1_REG);
unsigned long end;
u32 val = 0;
end = msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS) + jiffies;
while (hns_roce_v1_cmd_pending(hr_dev)) {
if (time_after(jiffies, end)) {
dev_err(hr_dev->dev, "jiffies=%d end=%d\n",
(int)jiffies, (int)end);
return -EAGAIN;
}
cond_resched();
}
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_M, ROCEE_MB6_ROCEE_MB_CMD_S,
op);
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_MDF_M,
ROCEE_MB6_ROCEE_MB_CMD_MDF_S, op_modifier);
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_EVENT_S, event);
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_HW_RUN_S, 1);
roce_set_field(val, ROCEE_MB6_ROCEE_MB_TOKEN_M,
ROCEE_MB6_ROCEE_MB_TOKEN_S, token);
__raw_writeq(cpu_to_le64(in_param), hcr + 0);
__raw_writeq(cpu_to_le64(out_param), hcr + 2);
__raw_writel(cpu_to_le32(in_modifier), hcr + 4);
/* Memory barrier */
wmb();
__raw_writel(cpu_to_le32(val), hcr + 5);
mmiowb();
return 0;
}
static int hns_roce_v1_chk_mbox(struct hns_roce_dev *hr_dev,
unsigned long timeout)
{
u8 __iomem *hcr = hr_dev->reg_base + ROCEE_MB1_REG;
unsigned long end = 0;
u32 status = 0;
end = msecs_to_jiffies(timeout) + jiffies;
while (hns_roce_v1_cmd_pending(hr_dev) && time_before(jiffies, end))
cond_resched();
if (hns_roce_v1_cmd_pending(hr_dev)) {
dev_err(hr_dev->dev, "[cmd_poll]hw run cmd TIMEDOUT!\n");
return -ETIMEDOUT;
}
status = le32_to_cpu((__force __be32)
__raw_readl(hcr + HCR_STATUS_OFFSET));
if ((status & STATUS_MASK) != 0x1) {
dev_err(hr_dev->dev, "mailbox status 0x%x!\n", status);
return -EBUSY;
}
return 0;
}
void hns_roce_v1_set_gid(struct hns_roce_dev *hr_dev, u8 port, int gid_index, void hns_roce_v1_set_gid(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
union ib_gid *gid) union ib_gid *gid)
{ {
...@@ -3849,6 +3922,8 @@ static const struct hns_roce_hw hns_roce_hw_v1 = { ...@@ -3849,6 +3922,8 @@ static const struct hns_roce_hw hns_roce_hw_v1 = {
.hw_profile = hns_roce_v1_profile, .hw_profile = hns_roce_v1_profile,
.hw_init = hns_roce_v1_init, .hw_init = hns_roce_v1_init,
.hw_exit = hns_roce_v1_exit, .hw_exit = hns_roce_v1_exit,
.post_mbox = hns_roce_v1_post_mbox,
.chk_mbox = hns_roce_v1_chk_mbox,
.set_gid = hns_roce_v1_set_gid, .set_gid = hns_roce_v1_set_gid,
.set_mac = hns_roce_v1_set_mac, .set_mac = hns_roce_v1_set_mac,
.set_mtu = hns_roce_v1_set_mtu, .set_mtu = hns_roce_v1_set_mtu,
......
...@@ -948,6 +948,11 @@ struct hns_roce_qp_context { ...@@ -948,6 +948,11 @@ struct hns_roce_qp_context {
#define QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_M \ #define QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_M \
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_S) (((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_S)
#define STATUS_MASK 0xff
#define GO_BIT_TIMEOUT_MSECS 10000
#define HCR_STATUS_OFFSET 0x18
#define HCR_GO_BIT 15
struct hns_roce_rq_db { struct hns_roce_rq_db {
u32 u32_4; u32 u32_4;
u32 u32_8; u32 u32_8;
......
...@@ -553,10 +553,94 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev) ...@@ -553,10 +553,94 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
return 0; return 0;
} }
static int hns_roce_v2_cmd_pending(struct hns_roce_dev *hr_dev)
{
u32 status = readl(hr_dev->reg_base + ROCEE_VF_MB_STATUS_REG);
return status >> HNS_ROCE_HW_RUN_BIT_SHIFT;
}
static int hns_roce_v2_cmd_complete(struct hns_roce_dev *hr_dev)
{
u32 status = readl(hr_dev->reg_base + ROCEE_VF_MB_STATUS_REG);
return status & HNS_ROCE_HW_MB_STATUS_MASK;
}
static int hns_roce_v2_post_mbox(struct hns_roce_dev *hr_dev, u64 in_param,
u64 out_param, u32 in_modifier, u8 op_modifier,
u16 op, u16 token, int event)
{
struct device *dev = hr_dev->dev;
u32 *hcr = (u32 *)(hr_dev->reg_base + ROCEE_VF_MB_CFG0_REG);
unsigned long end;
u32 val0 = 0;
u32 val1 = 0;
end = msecs_to_jiffies(HNS_ROCE_V2_GO_BIT_TIMEOUT_MSECS) + jiffies;
while (hns_roce_v2_cmd_pending(hr_dev)) {
if (time_after(jiffies, end)) {
dev_dbg(dev, "jiffies=%d end=%d\n", (int)jiffies,
(int)end);
return -EAGAIN;
}
cond_resched();
}
roce_set_field(val0, HNS_ROCE_VF_MB4_TAG_MASK,
HNS_ROCE_VF_MB4_TAG_SHIFT, in_modifier);
roce_set_field(val0, HNS_ROCE_VF_MB4_CMD_MASK,
HNS_ROCE_VF_MB4_CMD_SHIFT, op);
roce_set_field(val1, HNS_ROCE_VF_MB5_EVENT_MASK,
HNS_ROCE_VF_MB5_EVENT_SHIFT, event);
roce_set_field(val1, HNS_ROCE_VF_MB5_TOKEN_MASK,
HNS_ROCE_VF_MB5_TOKEN_SHIFT, token);
__raw_writeq(cpu_to_le64(in_param), hcr + 0);
__raw_writeq(cpu_to_le64(out_param), hcr + 2);
/* Memory barrier */
wmb();
__raw_writel(cpu_to_le32(val0), hcr + 4);
__raw_writel(cpu_to_le32(val1), hcr + 5);
mmiowb();
return 0;
}
static int hns_roce_v2_chk_mbox(struct hns_roce_dev *hr_dev,
unsigned long timeout)
{
struct device *dev = hr_dev->dev;
unsigned long end = 0;
u32 status;
end = msecs_to_jiffies(timeout) + jiffies;
while (hns_roce_v2_cmd_pending(hr_dev) && time_before(jiffies, end))
cond_resched();
if (hns_roce_v2_cmd_pending(hr_dev)) {
dev_err(dev, "[cmd_poll]hw run cmd TIMEDOUT!\n");
return -ETIMEDOUT;
}
status = hns_roce_v2_cmd_complete(hr_dev);
if (status != 0x1) {
dev_err(dev, "mailbox status 0x%x!\n", status);
return -EBUSY;
}
return 0;
}
static const struct hns_roce_hw hns_roce_hw_v2 = { static const struct hns_roce_hw hns_roce_hw_v2 = {
.cmq_init = hns_roce_v2_cmq_init, .cmq_init = hns_roce_v2_cmq_init,
.cmq_exit = hns_roce_v2_cmq_exit, .cmq_exit = hns_roce_v2_cmq_exit,
.hw_profile = hns_roce_v2_profile, .hw_profile = hns_roce_v2_profile,
.post_mbox = hns_roce_v2_post_mbox,
.chk_mbox = hns_roce_v2_chk_mbox,
}; };
static const struct pci_device_id hns_roce_hw_v2_pci_tbl[] = { static const struct pci_device_id hns_roce_hw_v2_pci_tbl[] = {
......
...@@ -244,6 +244,26 @@ struct hns_roce_cmq_desc { ...@@ -244,6 +244,26 @@ struct hns_roce_cmq_desc {
u32 data[6]; u32 data[6];
}; };
#define ROCEE_VF_MB_CFG0_REG 0x40
#define ROCEE_VF_MB_STATUS_REG 0x58
#define HNS_ROCE_V2_GO_BIT_TIMEOUT_MSECS 10000
#define HNS_ROCE_HW_RUN_BIT_SHIFT 31
#define HNS_ROCE_HW_MB_STATUS_MASK 0xFF
#define HNS_ROCE_VF_MB4_TAG_MASK 0xFFFFFF00
#define HNS_ROCE_VF_MB4_TAG_SHIFT 8
#define HNS_ROCE_VF_MB4_CMD_MASK 0xFF
#define HNS_ROCE_VF_MB4_CMD_SHIFT 0
#define HNS_ROCE_VF_MB5_EVENT_MASK 0x10000
#define HNS_ROCE_VF_MB5_EVENT_SHIFT 16
#define HNS_ROCE_VF_MB5_TOKEN_MASK 0xFFFF
#define HNS_ROCE_VF_MB5_TOKEN_SHIFT 0
struct hns_roce_v2_cmq_ring { struct hns_roce_v2_cmq_ring {
dma_addr_t desc_dma_addr; dma_addr_t desc_dma_addr;
struct hns_roce_cmq_desc *desc; struct hns_roce_cmq_desc *desc;
......
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