mirror of https://gitee.com/openkylin/linux.git
IB/hns: Add driver files for hns RoCE driver
These are the various new source code files for the Hisilicon RoCE driver for ARM architecture. Signed-off-by: Wei Hu <xavier.huwei@huawei.com> Signed-off-by: Nenglong Zhao <zhaonenglong@hisilicon.com> Signed-off-by: Lijun Ou <oulijun@huawei.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
69bafce807
commit
9a4435375c
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* 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 <rdma/ib_addr.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
#include "hns_roce_device.h"
|
||||
|
||||
#define HNS_ROCE_PORT_NUM_SHIFT 24
|
||||
#define HNS_ROCE_VLAN_SL_BIT_MASK 7
|
||||
#define HNS_ROCE_VLAN_SL_SHIFT 13
|
||||
|
||||
struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *ah_attr)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibpd->device);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct ib_gid_attr gid_attr;
|
||||
struct hns_roce_ah *ah;
|
||||
u16 vlan_tag = 0xffff;
|
||||
struct in6_addr in6;
|
||||
union ib_gid sgid;
|
||||
int ret;
|
||||
|
||||
ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
|
||||
if (!ah)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Get mac address */
|
||||
memcpy(&in6, ah_attr->grh.dgid.raw, sizeof(ah_attr->grh.dgid.raw));
|
||||
if (rdma_is_multicast_addr(&in6))
|
||||
rdma_get_mcast_mac(&in6, ah->av.mac);
|
||||
else
|
||||
memcpy(ah->av.mac, ah_attr->dmac, sizeof(ah_attr->dmac));
|
||||
|
||||
/* Get source gid */
|
||||
ret = ib_get_cached_gid(ibpd->device, ah_attr->port_num,
|
||||
ah_attr->grh.sgid_index, &sgid, &gid_attr);
|
||||
if (ret) {
|
||||
dev_err(dev, "get sgid failed! ret = %d\n", ret);
|
||||
kfree(ah);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (gid_attr.ndev) {
|
||||
if (is_vlan_dev(gid_attr.ndev))
|
||||
vlan_tag = vlan_dev_vlan_id(gid_attr.ndev);
|
||||
dev_put(gid_attr.ndev);
|
||||
}
|
||||
|
||||
if (vlan_tag < 0x1000)
|
||||
vlan_tag |= (ah_attr->sl & HNS_ROCE_VLAN_SL_BIT_MASK) <<
|
||||
HNS_ROCE_VLAN_SL_SHIFT;
|
||||
|
||||
ah->av.port_pd = cpu_to_be32(to_hr_pd(ibpd)->pdn | (ah_attr->port_num <<
|
||||
HNS_ROCE_PORT_NUM_SHIFT));
|
||||
ah->av.gid_index = ah_attr->grh.sgid_index;
|
||||
ah->av.vlan = cpu_to_le16(vlan_tag);
|
||||
dev_dbg(dev, "gid_index = 0x%x,vlan = 0x%x\n", ah->av.gid_index,
|
||||
ah->av.vlan);
|
||||
|
||||
if (ah_attr->static_rate)
|
||||
ah->av.stat_rate = IB_RATE_10_GBPS;
|
||||
|
||||
memcpy(ah->av.dgid, ah_attr->grh.dgid.raw, HNS_ROCE_GID_SIZE);
|
||||
ah->av.sl_tclass_flowlabel = cpu_to_le32(ah_attr->sl <<
|
||||
HNS_ROCE_SL_SHIFT);
|
||||
|
||||
return &ah->ibah;
|
||||
}
|
||||
|
||||
int hns_roce_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
|
||||
{
|
||||
struct hns_roce_ah *ah = to_hr_ah(ibah);
|
||||
|
||||
memset(ah_attr, 0, sizeof(*ah_attr));
|
||||
|
||||
ah_attr->sl = le32_to_cpu(ah->av.sl_tclass_flowlabel) >>
|
||||
HNS_ROCE_SL_SHIFT;
|
||||
ah_attr->port_num = le32_to_cpu(ah->av.port_pd) >>
|
||||
HNS_ROCE_PORT_NUM_SHIFT;
|
||||
ah_attr->static_rate = ah->av.stat_rate;
|
||||
ah_attr->ah_flags = IB_AH_GRH;
|
||||
ah_attr->grh.traffic_class = le32_to_cpu(ah->av.sl_tclass_flowlabel) >>
|
||||
HNS_ROCE_TCLASS_SHIFT;
|
||||
ah_attr->grh.flow_label = le32_to_cpu(ah->av.sl_tclass_flowlabel) &
|
||||
HNS_ROCE_FLOW_LABLE_MASK;
|
||||
ah_attr->grh.hop_limit = ah->av.hop_limit;
|
||||
ah_attr->grh.sgid_index = ah->av.gid_index;
|
||||
memcpy(ah_attr->grh.dgid.raw, ah->av.dgid, HNS_ROCE_GID_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_destroy_ah(struct ib_ah *ah)
|
||||
{
|
||||
kfree(to_hr_ah(ah));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Hisilicon Limited.
|
||||
* Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* 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 "hns_roce_device.h"
|
||||
|
||||
int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&bitmap->lock);
|
||||
*obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
|
||||
if (*obj >= bitmap->max) {
|
||||
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
|
||||
& bitmap->mask;
|
||||
*obj = find_first_zero_bit(bitmap->table, bitmap->max);
|
||||
}
|
||||
|
||||
if (*obj < bitmap->max) {
|
||||
set_bit(*obj, bitmap->table);
|
||||
bitmap->last = (*obj + 1);
|
||||
if (bitmap->last == bitmap->max)
|
||||
bitmap->last = 0;
|
||||
*obj |= bitmap->top;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
spin_unlock(&bitmap->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj)
|
||||
{
|
||||
hns_roce_bitmap_free_range(bitmap, obj, 1);
|
||||
}
|
||||
|
||||
int hns_roce_bitmap_alloc_range(struct hns_roce_bitmap *bitmap, int cnt,
|
||||
int align, unsigned long *obj)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (likely(cnt == 1 && align == 1))
|
||||
return hns_roce_bitmap_alloc(bitmap, obj);
|
||||
|
||||
spin_lock(&bitmap->lock);
|
||||
|
||||
*obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max,
|
||||
bitmap->last, cnt, align - 1);
|
||||
if (*obj >= bitmap->max) {
|
||||
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
|
||||
& bitmap->mask;
|
||||
*obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, 0,
|
||||
cnt, align - 1);
|
||||
}
|
||||
|
||||
if (*obj < bitmap->max) {
|
||||
for (i = 0; i < cnt; i++)
|
||||
set_bit(*obj + i, bitmap->table);
|
||||
|
||||
if (*obj == bitmap->last) {
|
||||
bitmap->last = (*obj + cnt);
|
||||
if (bitmap->last >= bitmap->max)
|
||||
bitmap->last = 0;
|
||||
}
|
||||
*obj |= bitmap->top;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
spin_unlock(&bitmap->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_bitmap_free_range(struct hns_roce_bitmap *bitmap,
|
||||
unsigned long obj, int cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
obj &= bitmap->max + bitmap->reserved_top - 1;
|
||||
|
||||
spin_lock(&bitmap->lock);
|
||||
for (i = 0; i < cnt; i++)
|
||||
clear_bit(obj + i, bitmap->table);
|
||||
|
||||
bitmap->last = min(bitmap->last, obj);
|
||||
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
|
||||
& bitmap->mask;
|
||||
spin_unlock(&bitmap->lock);
|
||||
}
|
||||
|
||||
int hns_roce_bitmap_init(struct hns_roce_bitmap *bitmap, u32 num, u32 mask,
|
||||
u32 reserved_bot, u32 reserved_top)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (num != roundup_pow_of_two(num))
|
||||
return -EINVAL;
|
||||
|
||||
bitmap->last = 0;
|
||||
bitmap->top = 0;
|
||||
bitmap->max = num - reserved_top;
|
||||
bitmap->mask = mask;
|
||||
bitmap->reserved_top = reserved_top;
|
||||
spin_lock_init(&bitmap->lock);
|
||||
bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long),
|
||||
GFP_KERNEL);
|
||||
if (!bitmap->table)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < reserved_bot; ++i)
|
||||
set_bit(i, bitmap->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_bitmap_cleanup(struct hns_roce_bitmap *bitmap)
|
||||
{
|
||||
kfree(bitmap->table);
|
||||
}
|
||||
|
||||
void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size,
|
||||
struct hns_roce_buf *buf)
|
||||
{
|
||||
int i;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u32 bits_per_long = BITS_PER_LONG;
|
||||
|
||||
if (buf->nbufs == 1) {
|
||||
dma_free_coherent(dev, size, buf->direct.buf, buf->direct.map);
|
||||
} else {
|
||||
if (bits_per_long == 64)
|
||||
vunmap(buf->direct.buf);
|
||||
|
||||
for (i = 0; i < buf->nbufs; ++i)
|
||||
if (buf->page_list[i].buf)
|
||||
dma_free_coherent(&hr_dev->pdev->dev, PAGE_SIZE,
|
||||
buf->page_list[i].buf,
|
||||
buf->page_list[i].map);
|
||||
kfree(buf->page_list);
|
||||
}
|
||||
}
|
||||
|
||||
int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
|
||||
struct hns_roce_buf *buf)
|
||||
{
|
||||
int i = 0;
|
||||
dma_addr_t t;
|
||||
struct page **pages;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u32 bits_per_long = BITS_PER_LONG;
|
||||
|
||||
/* SQ/RQ buf lease than one page, SQ + RQ = 8K */
|
||||
if (size <= max_direct) {
|
||||
buf->nbufs = 1;
|
||||
/* Npages calculated by page_size */
|
||||
buf->npages = 1 << get_order(size);
|
||||
buf->page_shift = PAGE_SHIFT;
|
||||
/* MTT PA must be recorded in 4k alignment, t is 4k aligned */
|
||||
buf->direct.buf = dma_alloc_coherent(dev, size, &t, GFP_KERNEL);
|
||||
if (!buf->direct.buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->direct.map = t;
|
||||
|
||||
while (t & ((1 << buf->page_shift) - 1)) {
|
||||
--buf->page_shift;
|
||||
buf->npages *= 2;
|
||||
}
|
||||
|
||||
memset(buf->direct.buf, 0, size);
|
||||
} else {
|
||||
buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
buf->npages = buf->nbufs;
|
||||
buf->page_shift = PAGE_SHIFT;
|
||||
buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!buf->page_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < buf->nbufs; ++i) {
|
||||
buf->page_list[i].buf = dma_alloc_coherent(dev,
|
||||
PAGE_SIZE, &t,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!buf->page_list[i].buf)
|
||||
goto err_free;
|
||||
|
||||
buf->page_list[i].map = t;
|
||||
memset(buf->page_list[i].buf, 0, PAGE_SIZE);
|
||||
}
|
||||
if (bits_per_long == 64) {
|
||||
pages = kmalloc_array(buf->nbufs, sizeof(*pages),
|
||||
GFP_KERNEL);
|
||||
if (!pages)
|
||||
goto err_free;
|
||||
|
||||
for (i = 0; i < buf->nbufs; ++i)
|
||||
pages[i] = virt_to_page(buf->page_list[i].buf);
|
||||
|
||||
buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP,
|
||||
PAGE_KERNEL);
|
||||
kfree(pages);
|
||||
if (!buf->direct.buf)
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
hns_roce_buf_free(hr_dev, size, buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_bitmap(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_cleanup_qp_table(hr_dev);
|
||||
hns_roce_cleanup_cq_table(hr_dev);
|
||||
hns_roce_cleanup_mr_table(hr_dev);
|
||||
hns_roce_cleanup_pd_table(hr_dev);
|
||||
hns_roce_cleanup_uar_table(hr_dev);
|
||||
}
|
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* 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/dmapool.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "hns_roce_common.h"
|
||||
#include "hns_roce_device.h"
|
||||
#include "hns_roce_cmd.h"
|
||||
|
||||
#define CMD_POLL_TOKEN 0xffff
|
||||
#define CMD_MAX_NUM 32
|
||||
#define STATUS_MASK 0xff
|
||||
#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,
|
||||
u64 out_param, u32 in_modifier,
|
||||
u8 op_modifier, u16 op, u16 token,
|
||||
int event)
|
||||
{
|
||||
struct hns_roce_cmdq *cmd = &hr_dev->cmd;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
mutex_lock(&cmd->hcr_mutex);
|
||||
ret = __hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op, token,
|
||||
event);
|
||||
mutex_unlock(&cmd->hcr_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* this should be called with "poll_sem" */
|
||||
static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u64 out_param, unsigned long in_modifier,
|
||||
u8 op_modifier, u16 op,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u8 __iomem *hcr = hr_dev->cmd.hcr;
|
||||
unsigned long end = 0;
|
||||
u32 status = 0;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op,
|
||||
CMD_POLL_TOKEN, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "[cmd_poll]hns_roce_cmd_mbox_post_hw failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
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)
|
||||
__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,
|
||||
u64 out_param, unsigned long in_modifier,
|
||||
u8 op_modifier, u16 op, unsigned long timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
down(&hr_dev->cmd.poll_sem);
|
||||
ret = __hns_roce_cmd_mbox_poll(hr_dev, in_param, out_param, in_modifier,
|
||||
op_modifier, op, timeout);
|
||||
up(&hr_dev->cmd.poll_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_cmd_event(struct hns_roce_dev *hr_dev, u16 token, u8 status,
|
||||
u64 out_param)
|
||||
{
|
||||
struct hns_roce_cmd_context
|
||||
*context = &hr_dev->cmd.context[token & hr_dev->cmd.token_mask];
|
||||
|
||||
if (token != context->token)
|
||||
return;
|
||||
|
||||
context->result = (status == HNS_ROCE_CMD_SUCCESS) ? 0 : (-EIO);
|
||||
context->out_param = out_param;
|
||||
complete(&context->done);
|
||||
}
|
||||
|
||||
/* this should be called with "use_events" */
|
||||
static int __hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u64 out_param, unsigned long in_modifier,
|
||||
u8 op_modifier, u16 op,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct hns_roce_cmdq *cmd = &hr_dev->cmd;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_cmd_context *context;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&cmd->context_lock);
|
||||
WARN_ON(cmd->free_head < 0);
|
||||
context = &cmd->context[cmd->free_head];
|
||||
context->token += cmd->token_mask + 1;
|
||||
cmd->free_head = context->next;
|
||||
spin_unlock(&cmd->context_lock);
|
||||
|
||||
init_completion(&context->done);
|
||||
|
||||
ret = hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op,
|
||||
context->token, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* It is timeout when wait_for_completion_timeout return 0
|
||||
* The return value is the time limit set in advance
|
||||
* how many seconds showing
|
||||
*/
|
||||
if (!wait_for_completion_timeout(&context->done,
|
||||
msecs_to_jiffies(timeout))) {
|
||||
dev_err(dev, "[cmd]wait_for_completion_timeout timeout\n");
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = context->result;
|
||||
if (ret) {
|
||||
dev_err(dev, "[cmd]event mod cmd process error!err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_lock(&cmd->context_lock);
|
||||
context->next = cmd->free_head;
|
||||
cmd->free_head = context - cmd->context;
|
||||
spin_unlock(&cmd->context_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u64 out_param, unsigned long in_modifier,
|
||||
u8 op_modifier, u16 op, unsigned long timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
down(&hr_dev->cmd.event_sem);
|
||||
ret = __hns_roce_cmd_mbox_wait(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op, timeout);
|
||||
up(&hr_dev->cmd.event_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 timeout)
|
||||
{
|
||||
if (hr_dev->cmd.use_events)
|
||||
return hns_roce_cmd_mbox_wait(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op,
|
||||
timeout);
|
||||
else
|
||||
return hns_roce_cmd_mbox_poll(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op,
|
||||
timeout);
|
||||
}
|
||||
|
||||
int hns_roce_cmd_init(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
|
||||
mutex_init(&hr_dev->cmd.hcr_mutex);
|
||||
sema_init(&hr_dev->cmd.poll_sem, 1);
|
||||
hr_dev->cmd.use_events = 0;
|
||||
hr_dev->cmd.toggle = 1;
|
||||
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,
|
||||
HNS_ROCE_MAILBOX_SIZE,
|
||||
HNS_ROCE_MAILBOX_SIZE, 0);
|
||||
if (!hr_dev->cmd.pool)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_cmd_cleanup(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
dma_pool_destroy(hr_dev->cmd.pool);
|
||||
}
|
||||
|
||||
int hns_roce_cmd_use_events(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_cmdq *hr_cmd = &hr_dev->cmd;
|
||||
int i;
|
||||
|
||||
hr_cmd->context = kmalloc(hr_cmd->max_cmds *
|
||||
sizeof(struct hns_roce_cmd_context),
|
||||
GFP_KERNEL);
|
||||
if (!hr_cmd->context)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < hr_cmd->max_cmds; ++i) {
|
||||
hr_cmd->context[i].token = i;
|
||||
hr_cmd->context[i].next = i + 1;
|
||||
}
|
||||
|
||||
hr_cmd->context[hr_cmd->max_cmds - 1].next = -1;
|
||||
hr_cmd->free_head = 0;
|
||||
|
||||
sema_init(&hr_cmd->event_sem, hr_cmd->max_cmds);
|
||||
spin_lock_init(&hr_cmd->context_lock);
|
||||
|
||||
hr_cmd->token_mask = CMD_TOKEN_MASK;
|
||||
hr_cmd->use_events = 1;
|
||||
|
||||
down(&hr_cmd->poll_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_cmdq *hr_cmd = &hr_dev->cmd;
|
||||
int i;
|
||||
|
||||
hr_cmd->use_events = 0;
|
||||
|
||||
for (i = 0; i < hr_cmd->max_cmds; ++i)
|
||||
down(&hr_cmd->event_sem);
|
||||
|
||||
kfree(hr_cmd->context);
|
||||
up(&hr_cmd->poll_sem);
|
||||
}
|
||||
|
||||
struct hns_roce_cmd_mailbox
|
||||
*hns_roce_alloc_cmd_mailbox(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_cmd_mailbox *mailbox;
|
||||
|
||||
mailbox = kmalloc(sizeof(*mailbox), GFP_KERNEL);
|
||||
if (!mailbox)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mailbox->buf = dma_pool_alloc(hr_dev->cmd.pool, GFP_KERNEL,
|
||||
&mailbox->dma);
|
||||
if (!mailbox->buf) {
|
||||
kfree(mailbox);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
void hns_roce_free_cmd_mailbox(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox)
|
||||
{
|
||||
if (!mailbox)
|
||||
return;
|
||||
|
||||
dma_pool_free(hr_dev->cmd.pool, mailbox->buf, mailbox->dma);
|
||||
kfree(mailbox);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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_CMD_H
|
||||
#define _HNS_ROCE_CMD_H
|
||||
|
||||
#define HNS_ROCE_MAILBOX_SIZE 4096
|
||||
|
||||
enum {
|
||||
/* TPT commands */
|
||||
HNS_ROCE_CMD_SW2HW_MPT = 0xd,
|
||||
HNS_ROCE_CMD_HW2SW_MPT = 0xf,
|
||||
|
||||
/* CQ commands */
|
||||
HNS_ROCE_CMD_SW2HW_CQ = 0x16,
|
||||
HNS_ROCE_CMD_HW2SW_CQ = 0x17,
|
||||
|
||||
/* QP/EE commands */
|
||||
HNS_ROCE_CMD_RST2INIT_QP = 0x19,
|
||||
HNS_ROCE_CMD_INIT2RTR_QP = 0x1a,
|
||||
HNS_ROCE_CMD_RTR2RTS_QP = 0x1b,
|
||||
HNS_ROCE_CMD_RTS2RTS_QP = 0x1c,
|
||||
HNS_ROCE_CMD_2ERR_QP = 0x1e,
|
||||
HNS_ROCE_CMD_RTS2SQD_QP = 0x1f,
|
||||
HNS_ROCE_CMD_SQD2SQD_QP = 0x38,
|
||||
HNS_ROCE_CMD_SQD2RTS_QP = 0x20,
|
||||
HNS_ROCE_CMD_2RST_QP = 0x21,
|
||||
HNS_ROCE_CMD_QUERY_QP = 0x22,
|
||||
};
|
||||
|
||||
enum {
|
||||
HNS_ROCE_CMD_TIME_CLASS_A = 10000,
|
||||
HNS_ROCE_CMD_TIME_CLASS_B = 10000,
|
||||
HNS_ROCE_CMD_TIME_CLASS_C = 10000,
|
||||
};
|
||||
|
||||
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,
|
||||
unsigned long in_modifier, u8 op_modifier, u16 op,
|
||||
unsigned long timeout);
|
||||
|
||||
struct hns_roce_cmd_mailbox
|
||||
*hns_roce_alloc_cmd_mailbox(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_free_cmd_mailbox(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox);
|
||||
|
||||
#endif /* _HNS_ROCE_CMD_H */
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* 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_COMMON_H
|
||||
#define _HNS_ROCE_COMMON_H
|
||||
|
||||
#ifndef assert
|
||||
#define assert(cond)
|
||||
#endif
|
||||
|
||||
#define roce_write(dev, reg, val) writel((val), (dev)->reg_base + (reg))
|
||||
#define roce_read(dev, reg) readl((dev)->reg_base + (reg))
|
||||
#define roce_raw_write(value, addr) \
|
||||
__raw_writel((__force u32)cpu_to_le32(value), (addr))
|
||||
|
||||
#define roce_get_field(origin, mask, shift) \
|
||||
(((origin) & (mask)) >> (shift))
|
||||
|
||||
#define roce_get_bit(origin, shift) \
|
||||
roce_get_field((origin), (1ul << (shift)), (shift))
|
||||
|
||||
#define roce_set_field(origin, mask, shift, val) \
|
||||
do { \
|
||||
(origin) &= (~(mask)); \
|
||||
(origin) |= (((u32)(val) << (shift)) & (mask)); \
|
||||
} while (0)
|
||||
|
||||
#define roce_set_bit(origin, shift, val) \
|
||||
roce_set_field((origin), (1ul << (shift)), (shift), (val))
|
||||
|
||||
#define ROCEE_GLB_CFG_ROCEE_DB_SQ_MODE_S 3
|
||||
#define ROCEE_GLB_CFG_ROCEE_DB_OTH_MODE_S 4
|
||||
|
||||
#define ROCEE_GLB_CFG_SQ_EXT_DB_MODE_S 5
|
||||
|
||||
#define ROCEE_GLB_CFG_OTH_EXT_DB_MODE_S 6
|
||||
|
||||
#define ROCEE_GLB_CFG_ROCEE_PORT_ST_S 10
|
||||
#define ROCEE_GLB_CFG_ROCEE_PORT_ST_M \
|
||||
(((1UL << 6) - 1) << ROCEE_GLB_CFG_ROCEE_PORT_ST_S)
|
||||
|
||||
#define ROCEE_GLB_CFG_TRP_RAQ_DROP_EN_S 16
|
||||
|
||||
#define ROCEE_DMAE_USER_CFG1_ROCEE_STREAM_ID_TB_CFG_S 0
|
||||
#define ROCEE_DMAE_USER_CFG1_ROCEE_STREAM_ID_TB_CFG_M \
|
||||
(((1UL << 24) - 1) << ROCEE_DMAE_USER_CFG1_ROCEE_STREAM_ID_TB_CFG_S)
|
||||
|
||||
#define ROCEE_DMAE_USER_CFG1_ROCEE_CACHE_TB_CFG_S 24
|
||||
#define ROCEE_DMAE_USER_CFG1_ROCEE_CACHE_TB_CFG_M \
|
||||
(((1UL << 4) - 1) << ROCEE_DMAE_USER_CFG1_ROCEE_CACHE_TB_CFG_S)
|
||||
|
||||
#define ROCEE_DMAE_USER_CFG2_ROCEE_STREAM_ID_PKT_CFG_S 0
|
||||
#define ROCEE_DMAE_USER_CFG2_ROCEE_STREAM_ID_PKT_CFG_M \
|
||||
(((1UL << 24) - 1) << ROCEE_DMAE_USER_CFG2_ROCEE_STREAM_ID_PKT_CFG_S)
|
||||
|
||||
#define ROCEE_DMAE_USER_CFG2_ROCEE_CACHE_PKT_CFG_S 24
|
||||
#define ROCEE_DMAE_USER_CFG2_ROCEE_CACHE_PKT_CFG_M \
|
||||
(((1UL << 4) - 1) << ROCEE_DMAE_USER_CFG2_ROCEE_CACHE_PKT_CFG_S)
|
||||
|
||||
#define ROCEE_DB_SQ_WL_ROCEE_DB_SQ_WL_S 0
|
||||
#define ROCEE_DB_SQ_WL_ROCEE_DB_SQ_WL_M \
|
||||
(((1UL << 16) - 1) << ROCEE_DB_SQ_WL_ROCEE_DB_SQ_WL_S)
|
||||
|
||||
#define ROCEE_DB_SQ_WL_ROCEE_DB_SQ_WL_EMPTY_S 16
|
||||
#define ROCEE_DB_SQ_WL_ROCEE_DB_SQ_WL_EMPTY_M \
|
||||
(((1UL << 16) - 1) << ROCEE_DB_SQ_WL_ROCEE_DB_SQ_WL_EMPTY_S)
|
||||
|
||||
#define ROCEE_DB_OTHERS_WL_ROCEE_DB_OTH_WL_S 0
|
||||
#define ROCEE_DB_OTHERS_WL_ROCEE_DB_OTH_WL_M \
|
||||
(((1UL << 16) - 1) << ROCEE_DB_OTHERS_WL_ROCEE_DB_OTH_WL_S)
|
||||
|
||||
#define ROCEE_DB_OTHERS_WL_ROCEE_DB_OTH_WL_EMPTY_S 16
|
||||
#define ROCEE_DB_OTHERS_WL_ROCEE_DB_OTH_WL_EMPTY_M \
|
||||
(((1UL << 16) - 1) << ROCEE_DB_OTHERS_WL_ROCEE_DB_OTH_WL_EMPTY_S)
|
||||
|
||||
#define ROCEE_RAQ_WL_ROCEE_RAQ_WL_S 0
|
||||
#define ROCEE_RAQ_WL_ROCEE_RAQ_WL_M \
|
||||
(((1UL << 8) - 1) << ROCEE_RAQ_WL_ROCEE_RAQ_WL_S)
|
||||
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_POL_TIME_INTERVAL_S 0
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_POL_TIME_INTERVAL_M \
|
||||
(((1UL << 15) - 1) << \
|
||||
ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_POL_TIME_INTERVAL_S)
|
||||
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_RAQ_TIMEOUT_CHK_CFG_S 16
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_RAQ_TIMEOUT_CHK_CFG_M \
|
||||
(((1UL << 4) - 1) << \
|
||||
ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_RAQ_TIMEOUT_CHK_CFG_S)
|
||||
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_RAQ_TIMEOUT_CHK_EN_S 20
|
||||
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_WRMS_EXT_RAQ_MODE 21
|
||||
|
||||
#define ROCEE_EXT_DB_SQ_H_EXT_DB_SQ_SHIFT_S 0
|
||||
#define ROCEE_EXT_DB_SQ_H_EXT_DB_SQ_SHIFT_M \
|
||||
(((1UL << 5) - 1) << ROCEE_EXT_DB_SQ_H_EXT_DB_SQ_SHIFT_S)
|
||||
|
||||
#define ROCEE_EXT_DB_SQ_H_EXT_DB_SQ_BA_H_S 5
|
||||
#define ROCEE_EXT_DB_SQ_H_EXT_DB_SQ_BA_H_M \
|
||||
(((1UL << 5) - 1) << ROCEE_EXT_DB_SQ_H_EXT_DB_SQ_BA_H_S)
|
||||
|
||||
#define ROCEE_EXT_DB_OTH_H_EXT_DB_OTH_SHIFT_S 0
|
||||
#define ROCEE_EXT_DB_OTH_H_EXT_DB_OTH_SHIFT_M \
|
||||
(((1UL << 5) - 1) << ROCEE_EXT_DB_OTH_H_EXT_DB_OTH_SHIFT_S)
|
||||
|
||||
#define ROCEE_EXT_DB_SQ_H_EXT_DB_OTH_BA_H_S 5
|
||||
#define ROCEE_EXT_DB_SQ_H_EXT_DB_OTH_BA_H_M \
|
||||
(((1UL << 5) - 1) << ROCEE_EXT_DB_SQ_H_EXT_DB_OTH_BA_H_S)
|
||||
|
||||
#define ROCEE_EXT_RAQ_H_EXT_RAQ_SHIFT_S 0
|
||||
#define ROCEE_EXT_RAQ_H_EXT_RAQ_SHIFT_M \
|
||||
(((1UL << 5) - 1) << ROCEE_EXT_RAQ_H_EXT_RAQ_SHIFT_S)
|
||||
|
||||
#define ROCEE_EXT_RAQ_H_EXT_RAQ_BA_H_S 8
|
||||
#define ROCEE_EXT_RAQ_H_EXT_RAQ_BA_H_M \
|
||||
(((1UL << 5) - 1) << ROCEE_EXT_RAQ_H_EXT_RAQ_BA_H_S)
|
||||
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S 0
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M \
|
||||
(((1UL << 19) - 1) << ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S)
|
||||
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_S 19
|
||||
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S 20
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M \
|
||||
(((1UL << 2) - 1) << ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S)
|
||||
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S 22
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M \
|
||||
(((1UL << 5) - 1) << ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S)
|
||||
|
||||
#define ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S 31
|
||||
|
||||
#define ROCEE_QP1C_CFG0_0_ROCEE_QP1C_QP_ST_S 0
|
||||
#define ROCEE_QP1C_CFG0_0_ROCEE_QP1C_QP_ST_M \
|
||||
(((1UL << 3) - 1) << ROCEE_QP1C_CFG0_0_ROCEE_QP1C_QP_ST_S)
|
||||
|
||||
#define ROCEE_QP1C_CFG3_0_ROCEE_QP1C_RQ_HEAD_S 0
|
||||
#define ROCEE_QP1C_CFG3_0_ROCEE_QP1C_RQ_HEAD_M \
|
||||
(((1UL << 15) - 1) << ROCEE_QP1C_CFG3_0_ROCEE_QP1C_RQ_HEAD_S)
|
||||
|
||||
#define ROCEE_MB6_ROCEE_MB_CMD_S 0
|
||||
#define ROCEE_MB6_ROCEE_MB_CMD_M \
|
||||
(((1UL << 8) - 1) << ROCEE_MB6_ROCEE_MB_CMD_S)
|
||||
|
||||
#define ROCEE_MB6_ROCEE_MB_CMD_MDF_S 8
|
||||
#define ROCEE_MB6_ROCEE_MB_CMD_MDF_M \
|
||||
(((1UL << 4) - 1) << ROCEE_MB6_ROCEE_MB_CMD_MDF_S)
|
||||
|
||||
#define ROCEE_MB6_ROCEE_MB_EVENT_S 14
|
||||
|
||||
#define ROCEE_MB6_ROCEE_MB_HW_RUN_S 15
|
||||
|
||||
#define ROCEE_MB6_ROCEE_MB_TOKEN_S 16
|
||||
#define ROCEE_MB6_ROCEE_MB_TOKEN_M \
|
||||
(((1UL << 16) - 1) << ROCEE_MB6_ROCEE_MB_TOKEN_S)
|
||||
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_INP_H_S 0
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_INP_H_M \
|
||||
(((1UL << 24) - 1) << ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_INP_H_S)
|
||||
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_MDF_S 24
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_MDF_M \
|
||||
(((1UL << 4) - 1) << ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_MDF_S)
|
||||
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_S 28
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_M \
|
||||
(((1UL << 3) - 1) << ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_S)
|
||||
|
||||
#define ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_HW_SYNS_S 31
|
||||
|
||||
#define ROCEE_SMAC_H_ROCEE_SMAC_H_S 0
|
||||
#define ROCEE_SMAC_H_ROCEE_SMAC_H_M \
|
||||
(((1UL << 16) - 1) << ROCEE_SMAC_H_ROCEE_SMAC_H_S)
|
||||
|
||||
#define ROCEE_SMAC_H_ROCEE_PORT_MTU_S 16
|
||||
#define ROCEE_SMAC_H_ROCEE_PORT_MTU_M \
|
||||
(((1UL << 4) - 1) << ROCEE_SMAC_H_ROCEE_PORT_MTU_S)
|
||||
|
||||
#define ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S 0
|
||||
#define ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_M \
|
||||
(((1UL << 2) - 1) << ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_STATE_S)
|
||||
|
||||
#define ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_S 8
|
||||
#define ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_M \
|
||||
(((1UL << 4) - 1) << ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQC_AEQE_SHIFT_S)
|
||||
|
||||
#define ROCEE_CAEP_AEQC_AEQE_SHIFT_CAEP_AEQ_ALM_OVF_INT_ST_S 17
|
||||
|
||||
#define ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_S 0
|
||||
#define ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_M \
|
||||
(((1UL << 5) - 1) << ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQ_BT_H_S)
|
||||
|
||||
#define ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_S 16
|
||||
#define ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_M \
|
||||
(((1UL << 16) - 1) << ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_S)
|
||||
|
||||
#define ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_S 0
|
||||
#define ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_M \
|
||||
(((1UL << 16) - 1) << ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_S)
|
||||
|
||||
#define ROCEE_CAEP_CEQC_SHIFT_CAEP_CEQ_ALM_OVF_INT_ST_S 16
|
||||
#define ROCEE_CAEP_CE_IRQ_MASK_CAEP_CEQ_ALM_OVF_MASK_S 1
|
||||
#define ROCEE_CAEP_CEQ_ALM_OVF_CAEP_CEQ_ALM_OVF_S 0
|
||||
|
||||
#define ROCEE_CAEP_AE_MASK_CAEP_AEQ_ALM_OVF_MASK_S 0
|
||||
#define ROCEE_CAEP_AE_MASK_CAEP_AE_IRQ_MASK_S 1
|
||||
|
||||
#define ROCEE_CAEP_AE_ST_CAEP_AEQ_ALM_OVF_S 0
|
||||
|
||||
#define ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_S 0
|
||||
#define ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_M \
|
||||
(((1UL << 28) - 1) << ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_S)
|
||||
|
||||
#define ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S 0
|
||||
#define ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M \
|
||||
(((1UL << 28) - 1) << ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S)
|
||||
|
||||
#define ROCEE_SDB_INV_CNT_SDB_INV_CNT_S 0
|
||||
#define ROCEE_SDB_INV_CNT_SDB_INV_CNT_M \
|
||||
(((1UL << 16) - 1) << ROCEE_SDB_INV_CNT_SDB_INV_CNT_S)
|
||||
|
||||
/*************ROCEE_REG DEFINITION****************/
|
||||
#define ROCEE_VENDOR_ID_REG 0x0
|
||||
#define ROCEE_VENDOR_PART_ID_REG 0x4
|
||||
|
||||
#define ROCEE_HW_VERSION_REG 0x8
|
||||
|
||||
#define ROCEE_SYS_IMAGE_GUID_L_REG 0xC
|
||||
#define ROCEE_SYS_IMAGE_GUID_H_REG 0x10
|
||||
|
||||
#define ROCEE_PORT_GID_L_0_REG 0x50
|
||||
#define ROCEE_PORT_GID_ML_0_REG 0x54
|
||||
#define ROCEE_PORT_GID_MH_0_REG 0x58
|
||||
#define ROCEE_PORT_GID_H_0_REG 0x5C
|
||||
|
||||
#define ROCEE_BT_CMD_H_REG 0x204
|
||||
|
||||
#define ROCEE_SMAC_L_0_REG 0x240
|
||||
#define ROCEE_SMAC_H_0_REG 0x244
|
||||
|
||||
#define ROCEE_QP1C_CFG3_0_REG 0x27C
|
||||
|
||||
#define ROCEE_CAEP_AEQE_CONS_IDX_REG 0x3AC
|
||||
#define ROCEE_CAEP_CEQC_CONS_IDX_0_REG 0x3BC
|
||||
|
||||
#define ROCEE_ECC_UCERR_ALM1_REG 0xB38
|
||||
#define ROCEE_ECC_UCERR_ALM2_REG 0xB3C
|
||||
#define ROCEE_ECC_CERR_ALM1_REG 0xB44
|
||||
#define ROCEE_ECC_CERR_ALM2_REG 0xB48
|
||||
|
||||
#define ROCEE_ACK_DELAY_REG 0x14
|
||||
#define ROCEE_GLB_CFG_REG 0x18
|
||||
|
||||
#define ROCEE_DMAE_USER_CFG1_REG 0x40
|
||||
#define ROCEE_DMAE_USER_CFG2_REG 0x44
|
||||
|
||||
#define ROCEE_DB_SQ_WL_REG 0x154
|
||||
#define ROCEE_DB_OTHERS_WL_REG 0x158
|
||||
#define ROCEE_RAQ_WL_REG 0x15C
|
||||
#define ROCEE_WRMS_POL_TIME_INTERVAL_REG 0x160
|
||||
#define ROCEE_EXT_DB_SQ_REG 0x164
|
||||
#define ROCEE_EXT_DB_SQ_H_REG 0x168
|
||||
#define ROCEE_EXT_DB_OTH_REG 0x16C
|
||||
|
||||
#define ROCEE_EXT_DB_OTH_H_REG 0x170
|
||||
#define ROCEE_EXT_DB_SQ_WL_EMPTY_REG 0x174
|
||||
#define ROCEE_EXT_DB_SQ_WL_REG 0x178
|
||||
#define ROCEE_EXT_DB_OTHERS_WL_EMPTY_REG 0x17C
|
||||
#define ROCEE_EXT_DB_OTHERS_WL_REG 0x180
|
||||
#define ROCEE_EXT_RAQ_REG 0x184
|
||||
#define ROCEE_EXT_RAQ_H_REG 0x188
|
||||
|
||||
#define ROCEE_CAEP_CE_INTERVAL_CFG_REG 0x190
|
||||
#define ROCEE_CAEP_CE_BURST_NUM_CFG_REG 0x194
|
||||
#define ROCEE_BT_CMD_L_REG 0x200
|
||||
|
||||
#define ROCEE_MB1_REG 0x210
|
||||
#define ROCEE_DB_SQ_L_0_REG 0x230
|
||||
#define ROCEE_DB_OTHERS_L_0_REG 0x238
|
||||
#define ROCEE_QP1C_CFG0_0_REG 0x270
|
||||
|
||||
#define ROCEE_CAEP_AEQC_AEQE_SHIFT_REG 0x3A0
|
||||
#define ROCEE_CAEP_CEQC_SHIFT_0_REG 0x3B0
|
||||
#define ROCEE_CAEP_CE_IRQ_MASK_0_REG 0x3C0
|
||||
#define ROCEE_CAEP_CEQ_ALM_OVF_0_REG 0x3C4
|
||||
#define ROCEE_CAEP_AE_MASK_REG 0x6C8
|
||||
#define ROCEE_CAEP_AE_ST_REG 0x6CC
|
||||
|
||||
#define ROCEE_SDB_ISSUE_PTR_REG 0x758
|
||||
#define ROCEE_SDB_SEND_PTR_REG 0x75C
|
||||
#define ROCEE_SDB_INV_CNT_REG 0x9A4
|
||||
#define ROCEE_ECC_UCERR_ALM0_REG 0xB34
|
||||
#define ROCEE_ECC_CERR_ALM0_REG 0xB40
|
||||
|
||||
#endif /* _HNS_ROCE_COMMON_H */
|
|
@ -0,0 +1,446 @@
|
|||
/*
|
||||
* 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 <rdma/ib_umem.h>
|
||||
#include "hns_roce_device.h"
|
||||
#include "hns_roce_cmd.h"
|
||||
#include "hns_roce_hem.h"
|
||||
#include "hns_roce_user.h"
|
||||
#include "hns_roce_common.h"
|
||||
|
||||
static void hns_roce_ib_cq_comp(struct hns_roce_cq *hr_cq)
|
||||
{
|
||||
struct ib_cq *ibcq = &hr_cq->ib_cq;
|
||||
|
||||
ibcq->comp_handler(ibcq, ibcq->cq_context);
|
||||
}
|
||||
|
||||
static void hns_roce_ib_cq_event(struct hns_roce_cq *hr_cq,
|
||||
enum hns_roce_event event_type)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev;
|
||||
struct ib_event event;
|
||||
struct ib_cq *ibcq;
|
||||
|
||||
ibcq = &hr_cq->ib_cq;
|
||||
hr_dev = to_hr_dev(ibcq->device);
|
||||
|
||||
if (event_type != HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID &&
|
||||
event_type != HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR &&
|
||||
event_type != HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW) {
|
||||
dev_err(&hr_dev->pdev->dev,
|
||||
"hns_roce_ib: Unexpected event type 0x%x on CQ %06lx\n",
|
||||
event_type, hr_cq->cqn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ibcq->event_handler) {
|
||||
event.device = ibcq->device;
|
||||
event.event = IB_EVENT_CQ_ERR;
|
||||
event.element.cq = ibcq;
|
||||
ibcq->event_handler(&event, ibcq->cq_context);
|
||||
}
|
||||
}
|
||||
|
||||
static int hns_roce_sw2hw_cq(struct hns_roce_dev *dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox,
|
||||
unsigned long cq_num)
|
||||
{
|
||||
return hns_roce_cmd_mbox(dev, mailbox->dma, 0, cq_num, 0,
|
||||
HNS_ROCE_CMD_SW2HW_CQ, HNS_ROCE_CMD_TIME_CLASS_A);
|
||||
}
|
||||
|
||||
static int hns_roce_cq_alloc(struct hns_roce_dev *hr_dev, int nent,
|
||||
struct hns_roce_mtt *hr_mtt,
|
||||
struct hns_roce_uar *hr_uar,
|
||||
struct hns_roce_cq *hr_cq, int vector,
|
||||
int collapsed)
|
||||
{
|
||||
struct hns_roce_cmd_mailbox *mailbox = NULL;
|
||||
struct hns_roce_cq_table *cq_table = NULL;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
dma_addr_t dma_handle;
|
||||
u64 *mtts = NULL;
|
||||
int ret = 0;
|
||||
|
||||
cq_table = &hr_dev->cq_table;
|
||||
|
||||
/* Get the physical address of cq buf */
|
||||
mtts = hns_roce_table_find(&hr_dev->mr_table.mtt_table,
|
||||
hr_mtt->first_seg, &dma_handle);
|
||||
if (!mtts) {
|
||||
dev_err(dev, "CQ alloc.Failed to find cq buf addr.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (vector >= hr_dev->caps.num_comp_vectors) {
|
||||
dev_err(dev, "CQ alloc.Invalid vector.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
hr_cq->vector = vector;
|
||||
|
||||
ret = hns_roce_bitmap_alloc(&cq_table->bitmap, &hr_cq->cqn);
|
||||
if (ret == -1) {
|
||||
dev_err(dev, "CQ alloc.Failed to alloc index.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get CQC memory HEM(Hardware Entry Memory) table */
|
||||
ret = hns_roce_table_get(hr_dev, &cq_table->table, hr_cq->cqn);
|
||||
if (ret) {
|
||||
dev_err(dev, "CQ alloc.Failed to get context mem.\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* The cq insert radix tree */
|
||||
spin_lock_irq(&cq_table->lock);
|
||||
/* Radix_tree: The associated pointer and long integer key value like */
|
||||
ret = radix_tree_insert(&cq_table->tree, hr_cq->cqn, hr_cq);
|
||||
spin_unlock_irq(&cq_table->lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "CQ alloc.Failed to radix_tree_insert.\n");
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
/* Allocate mailbox memory */
|
||||
mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
|
||||
if (IS_ERR(mailbox)) {
|
||||
ret = PTR_ERR(mailbox);
|
||||
goto err_radix;
|
||||
}
|
||||
|
||||
hr_dev->hw->write_cqc(hr_dev, hr_cq, mailbox->buf, mtts, dma_handle,
|
||||
nent, vector);
|
||||
|
||||
/* Send mailbox to hw */
|
||||
ret = hns_roce_sw2hw_cq(hr_dev, mailbox, hr_cq->cqn);
|
||||
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
|
||||
if (ret) {
|
||||
dev_err(dev, "CQ alloc.Failed to cmd mailbox.\n");
|
||||
goto err_radix;
|
||||
}
|
||||
|
||||
hr_cq->cons_index = 0;
|
||||
hr_cq->uar = hr_uar;
|
||||
|
||||
return 0;
|
||||
|
||||
err_radix:
|
||||
spin_lock_irq(&cq_table->lock);
|
||||
radix_tree_delete(&cq_table->tree, hr_cq->cqn);
|
||||
spin_unlock_irq(&cq_table->lock);
|
||||
|
||||
err_put:
|
||||
hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
|
||||
|
||||
err_out:
|
||||
hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_hw2sw_cq(struct hns_roce_dev *dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox,
|
||||
unsigned long cq_num)
|
||||
{
|
||||
return hns_roce_cmd_mbox(dev, 0, mailbox ? mailbox->dma : 0, cq_num,
|
||||
mailbox ? 0 : 1, HNS_ROCE_CMD_HW2SW_CQ,
|
||||
HNS_ROCE_CMD_TIME_CLASS_A);
|
||||
}
|
||||
|
||||
static void hns_roce_free_cq(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq *hr_cq)
|
||||
{
|
||||
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_hw2sw_cq(hr_dev, NULL, hr_cq->cqn);
|
||||
if (ret)
|
||||
dev_err(dev, "HW2SW_CQ failed (%d) for CQN %06lx\n", ret,
|
||||
hr_cq->cqn);
|
||||
|
||||
/* Waiting interrupt process procedure carried out */
|
||||
synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq);
|
||||
|
||||
spin_lock_irq(&cq_table->lock);
|
||||
radix_tree_delete(&cq_table->tree, hr_cq->cqn);
|
||||
spin_unlock_irq(&cq_table->lock);
|
||||
|
||||
hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
|
||||
hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn);
|
||||
}
|
||||
|
||||
static int hns_roce_ib_get_cq_umem(struct hns_roce_dev *hr_dev,
|
||||
struct ib_ucontext *context,
|
||||
struct hns_roce_cq_buf *buf,
|
||||
struct ib_umem **umem, u64 buf_addr, int cqe)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*umem = ib_umem_get(context, buf_addr, cqe * hr_dev->caps.cq_entry_sz,
|
||||
IB_ACCESS_LOCAL_WRITE, 1);
|
||||
if (IS_ERR(*umem))
|
||||
return PTR_ERR(*umem);
|
||||
|
||||
ret = hns_roce_mtt_init(hr_dev, ib_umem_page_count(*umem),
|
||||
ilog2((unsigned int)(*umem)->page_size),
|
||||
&buf->hr_mtt);
|
||||
if (ret)
|
||||
goto err_buf;
|
||||
|
||||
ret = hns_roce_ib_umem_write_mtt(hr_dev, &buf->hr_mtt, *umem);
|
||||
if (ret)
|
||||
goto err_mtt;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mtt:
|
||||
hns_roce_mtt_cleanup(hr_dev, &buf->hr_mtt);
|
||||
|
||||
err_buf:
|
||||
ib_umem_release(*umem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_ib_alloc_cq_buf(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq_buf *buf, u32 nent)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_buf_alloc(hr_dev, nent * hr_dev->caps.cq_entry_sz,
|
||||
PAGE_SIZE * 2, &buf->hr_buf);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = hns_roce_mtt_init(hr_dev, buf->hr_buf.npages,
|
||||
buf->hr_buf.page_shift, &buf->hr_mtt);
|
||||
if (ret)
|
||||
goto err_buf;
|
||||
|
||||
ret = hns_roce_buf_write_mtt(hr_dev, &buf->hr_mtt, &buf->hr_buf);
|
||||
if (ret)
|
||||
goto err_mtt;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mtt:
|
||||
hns_roce_mtt_cleanup(hr_dev, &buf->hr_mtt);
|
||||
|
||||
err_buf:
|
||||
hns_roce_buf_free(hr_dev, nent * hr_dev->caps.cq_entry_sz,
|
||||
&buf->hr_buf);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hns_roce_ib_free_cq_buf(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq_buf *buf, int cqe)
|
||||
{
|
||||
hns_roce_buf_free(hr_dev, (cqe + 1) * hr_dev->caps.cq_entry_sz,
|
||||
&buf->hr_buf);
|
||||
}
|
||||
|
||||
struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
|
||||
const struct ib_cq_init_attr *attr,
|
||||
struct ib_ucontext *context,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_ib_create_cq ucmd;
|
||||
struct hns_roce_cq *hr_cq = NULL;
|
||||
struct hns_roce_uar *uar = NULL;
|
||||
int vector = attr->comp_vector;
|
||||
int cq_entries = attr->cqe;
|
||||
int ret = 0;
|
||||
|
||||
if (cq_entries < 1 || cq_entries > hr_dev->caps.max_cqes) {
|
||||
dev_err(dev, "Creat CQ failed. entries=%d, max=%d\n",
|
||||
cq_entries, hr_dev->caps.max_cqes);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
hr_cq = kmalloc(sizeof(*hr_cq), GFP_KERNEL);
|
||||
if (!hr_cq)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* In v1 engine, parameter verification */
|
||||
if (cq_entries < HNS_ROCE_MIN_CQE_NUM)
|
||||
cq_entries = HNS_ROCE_MIN_CQE_NUM;
|
||||
|
||||
cq_entries = roundup_pow_of_two((unsigned int)cq_entries);
|
||||
hr_cq->ib_cq.cqe = cq_entries - 1;
|
||||
mutex_init(&hr_cq->resize_mutex);
|
||||
spin_lock_init(&hr_cq->lock);
|
||||
hr_cq->hr_resize_buf = NULL;
|
||||
hr_cq->resize_umem = NULL;
|
||||
|
||||
if (context) {
|
||||
if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
|
||||
dev_err(dev, "Failed to copy_from_udata.\n");
|
||||
ret = -EFAULT;
|
||||
goto err_cq;
|
||||
}
|
||||
|
||||
/* Get user space address, write it into mtt table */
|
||||
ret = hns_roce_ib_get_cq_umem(hr_dev, context, &hr_cq->hr_buf,
|
||||
&hr_cq->umem, ucmd.buf_addr,
|
||||
cq_entries);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get_cq_umem.\n");
|
||||
goto err_cq;
|
||||
}
|
||||
|
||||
/* Get user space parameters */
|
||||
uar = &to_hr_ucontext(context)->uar;
|
||||
} else {
|
||||
/* Init mmt table and write buff address to mtt table */
|
||||
ret = hns_roce_ib_alloc_cq_buf(hr_dev, &hr_cq->hr_buf,
|
||||
cq_entries);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to alloc_cq_buf.\n");
|
||||
goto err_cq;
|
||||
}
|
||||
|
||||
uar = &hr_dev->priv_uar;
|
||||
hr_cq->cq_db_l = hr_dev->reg_base + ROCEE_DB_OTHERS_L_0_REG +
|
||||
0x1000 * uar->index;
|
||||
}
|
||||
|
||||
/* Allocate cq index, fill cq_context */
|
||||
ret = hns_roce_cq_alloc(hr_dev, cq_entries, &hr_cq->hr_buf.hr_mtt,
|
||||
uar, hr_cq, vector, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Creat CQ .Failed to cq_alloc.\n");
|
||||
goto err_mtt;
|
||||
}
|
||||
|
||||
/* Get created cq handler and carry out event */
|
||||
hr_cq->comp = hns_roce_ib_cq_comp;
|
||||
hr_cq->event = hns_roce_ib_cq_event;
|
||||
hr_cq->cq_depth = cq_entries;
|
||||
|
||||
if (context) {
|
||||
if (ib_copy_to_udata(udata, &hr_cq->cqn, sizeof(u64))) {
|
||||
ret = -EFAULT;
|
||||
goto err_mtt;
|
||||
}
|
||||
}
|
||||
|
||||
return &hr_cq->ib_cq;
|
||||
|
||||
err_mtt:
|
||||
hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
|
||||
if (context)
|
||||
ib_umem_release(hr_cq->umem);
|
||||
else
|
||||
hns_roce_ib_free_cq_buf(hr_dev, &hr_cq->hr_buf,
|
||||
hr_cq->ib_cq.cqe);
|
||||
|
||||
err_cq:
|
||||
kfree(hr_cq);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
int hns_roce_ib_destroy_cq(struct ib_cq *ib_cq)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_cq->device);
|
||||
struct hns_roce_cq *hr_cq = to_hr_cq(ib_cq);
|
||||
|
||||
hns_roce_free_cq(hr_dev, hr_cq);
|
||||
hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
|
||||
|
||||
if (ib_cq->uobject)
|
||||
ib_umem_release(hr_cq->umem);
|
||||
else
|
||||
/* Free the buff of stored cq */
|
||||
hns_roce_ib_free_cq_buf(hr_dev, &hr_cq->hr_buf, ib_cq->cqe);
|
||||
|
||||
kfree(hr_cq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_cq *cq;
|
||||
|
||||
cq = radix_tree_lookup(&hr_dev->cq_table.tree,
|
||||
cqn & (hr_dev->caps.num_cqs - 1));
|
||||
if (!cq) {
|
||||
dev_warn(dev, "Completion event for bogus CQ 0x%08x\n", cqn);
|
||||
return;
|
||||
}
|
||||
|
||||
cq->comp(cq);
|
||||
}
|
||||
|
||||
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
|
||||
{
|
||||
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_cq *cq;
|
||||
|
||||
cq = radix_tree_lookup(&cq_table->tree,
|
||||
cqn & (hr_dev->caps.num_cqs - 1));
|
||||
if (cq)
|
||||
atomic_inc(&cq->refcount);
|
||||
|
||||
if (!cq) {
|
||||
dev_warn(dev, "Async event for bogus CQ %08x\n", cqn);
|
||||
return;
|
||||
}
|
||||
|
||||
cq->event(cq, (enum hns_roce_event)event_type);
|
||||
|
||||
if (atomic_dec_and_test(&cq->refcount))
|
||||
complete(&cq->free);
|
||||
}
|
||||
|
||||
int hns_roce_init_cq_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
||||
|
||||
spin_lock_init(&cq_table->lock);
|
||||
INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC);
|
||||
|
||||
return hns_roce_bitmap_init(&cq_table->bitmap, hr_dev->caps.num_cqs,
|
||||
hr_dev->caps.num_cqs - 1,
|
||||
hr_dev->caps.reserved_cqs, 0);
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_cq_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_bitmap_cleanup(&hr_dev->cq_table.bitmap);
|
||||
}
|
|
@ -0,0 +1,734 @@
|
|||
/*
|
||||
* 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_DEVICE_H
|
||||
#define _HNS_ROCE_DEVICE_H
|
||||
|
||||
#include <rdma/ib_verbs.h>
|
||||
|
||||
#define DRV_NAME "hns_roce"
|
||||
|
||||
#define MAC_ADDR_OCTET_NUM 6
|
||||
#define HNS_ROCE_MAX_MSG_LEN 0x80000000
|
||||
|
||||
#define HNS_ROCE_ALOGN_UP(a, b) ((((a) + (b) - 1) / (b)) * (b))
|
||||
|
||||
#define HNS_ROCE_IB_MIN_SQ_STRIDE 6
|
||||
|
||||
#define HNS_ROCE_BA_SIZE (32 * 4096)
|
||||
|
||||
/* Hardware specification only for v1 engine */
|
||||
#define HNS_ROCE_MIN_CQE_NUM 0x40
|
||||
#define HNS_ROCE_MIN_WQE_NUM 0x20
|
||||
|
||||
/* Hardware specification only for v1 engine */
|
||||
#define HNS_ROCE_MAX_INNER_MTPT_NUM 0x7
|
||||
#define HNS_ROCE_MAX_MTPT_PBL_NUM 0x100000
|
||||
|
||||
#define HNS_ROCE_MAX_IRQ_NUM 34
|
||||
|
||||
#define HNS_ROCE_COMP_VEC_NUM 32
|
||||
|
||||
#define HNS_ROCE_AEQE_VEC_NUM 1
|
||||
#define HNS_ROCE_AEQE_OF_VEC_NUM 1
|
||||
|
||||
/* 4G/4K = 1M */
|
||||
#define HNS_ROCE_SL_SHIFT 29
|
||||
#define HNS_ROCE_TCLASS_SHIFT 20
|
||||
#define HNS_ROCE_FLOW_LABLE_MASK 0xfffff
|
||||
|
||||
#define HNS_ROCE_MAX_PORTS 6
|
||||
#define HNS_ROCE_MAX_GID_NUM 16
|
||||
#define HNS_ROCE_GID_SIZE 16
|
||||
|
||||
#define MR_TYPE_MR 0x00
|
||||
#define MR_TYPE_DMA 0x03
|
||||
|
||||
#define PKEY_ID 0xffff
|
||||
#define NODE_DESC_SIZE 64
|
||||
|
||||
#define SERV_TYPE_RC 0
|
||||
#define SERV_TYPE_RD 1
|
||||
#define SERV_TYPE_UC 2
|
||||
#define SERV_TYPE_UD 3
|
||||
|
||||
#define PAGES_SHIFT_8 8
|
||||
#define PAGES_SHIFT_16 16
|
||||
#define PAGES_SHIFT_24 24
|
||||
#define PAGES_SHIFT_32 32
|
||||
|
||||
enum hns_roce_qp_state {
|
||||
HNS_ROCE_QP_STATE_RST,
|
||||
HNS_ROCE_QP_STATE_INIT,
|
||||
HNS_ROCE_QP_STATE_RTR,
|
||||
HNS_ROCE_QP_STATE_RTS,
|
||||
HNS_ROCE_QP_STATE_SQD,
|
||||
HNS_ROCE_QP_STATE_ERR,
|
||||
HNS_ROCE_QP_NUM_STATE,
|
||||
};
|
||||
|
||||
enum hns_roce_event {
|
||||
HNS_ROCE_EVENT_TYPE_PATH_MIG = 0x01,
|
||||
HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED = 0x02,
|
||||
HNS_ROCE_EVENT_TYPE_COMM_EST = 0x03,
|
||||
HNS_ROCE_EVENT_TYPE_SQ_DRAINED = 0x04,
|
||||
HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR = 0x05,
|
||||
HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR = 0x06,
|
||||
HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR = 0x07,
|
||||
HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH = 0x08,
|
||||
HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH = 0x09,
|
||||
HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR = 0x0a,
|
||||
HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR = 0x0b,
|
||||
HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW = 0x0c,
|
||||
HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID = 0x0d,
|
||||
HNS_ROCE_EVENT_TYPE_PORT_CHANGE = 0x0f,
|
||||
/* 0x10 and 0x11 is unused in currently application case */
|
||||
HNS_ROCE_EVENT_TYPE_DB_OVERFLOW = 0x12,
|
||||
HNS_ROCE_EVENT_TYPE_MB = 0x13,
|
||||
HNS_ROCE_EVENT_TYPE_CEQ_OVERFLOW = 0x14,
|
||||
};
|
||||
|
||||
/* Local Work Queue Catastrophic Error,SUBTYPE 0x5 */
|
||||
enum {
|
||||
HNS_ROCE_LWQCE_QPC_ERROR = 1,
|
||||
HNS_ROCE_LWQCE_MTU_ERROR = 2,
|
||||
HNS_ROCE_LWQCE_WQE_BA_ADDR_ERROR = 3,
|
||||
HNS_ROCE_LWQCE_WQE_ADDR_ERROR = 4,
|
||||
HNS_ROCE_LWQCE_SQ_WQE_SHIFT_ERROR = 5,
|
||||
HNS_ROCE_LWQCE_SL_ERROR = 6,
|
||||
HNS_ROCE_LWQCE_PORT_ERROR = 7,
|
||||
};
|
||||
|
||||
/* Local Access Violation Work Queue Error,SUBTYPE 0x7 */
|
||||
enum {
|
||||
HNS_ROCE_LAVWQE_R_KEY_VIOLATION = 1,
|
||||
HNS_ROCE_LAVWQE_LENGTH_ERROR = 2,
|
||||
HNS_ROCE_LAVWQE_VA_ERROR = 3,
|
||||
HNS_ROCE_LAVWQE_PD_ERROR = 4,
|
||||
HNS_ROCE_LAVWQE_RW_ACC_ERROR = 5,
|
||||
HNS_ROCE_LAVWQE_KEY_STATE_ERROR = 6,
|
||||
HNS_ROCE_LAVWQE_MR_OPERATION_ERROR = 7,
|
||||
};
|
||||
|
||||
/* DOORBELL overflow subtype */
|
||||
enum {
|
||||
HNS_ROCE_DB_SUBTYPE_SDB_OVF = 1,
|
||||
HNS_ROCE_DB_SUBTYPE_SDB_ALM_OVF = 2,
|
||||
HNS_ROCE_DB_SUBTYPE_ODB_OVF = 3,
|
||||
HNS_ROCE_DB_SUBTYPE_ODB_ALM_OVF = 4,
|
||||
HNS_ROCE_DB_SUBTYPE_SDB_ALM_EMP = 5,
|
||||
HNS_ROCE_DB_SUBTYPE_ODB_ALM_EMP = 6,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* RQ&SRQ related operations */
|
||||
HNS_ROCE_OPCODE_SEND_DATA_RECEIVE = 0x06,
|
||||
HNS_ROCE_OPCODE_RDMA_WITH_IMM_RECEIVE = 0x07,
|
||||
};
|
||||
|
||||
#define HNS_ROCE_CMD_SUCCESS 1
|
||||
|
||||
#define HNS_ROCE_PORT_DOWN 0
|
||||
#define HNS_ROCE_PORT_UP 1
|
||||
|
||||
#define HNS_ROCE_MTT_ENTRY_PER_SEG 8
|
||||
|
||||
#define PAGE_ADDR_SHIFT 12
|
||||
|
||||
struct hns_roce_uar {
|
||||
u64 pfn;
|
||||
unsigned long index;
|
||||
};
|
||||
|
||||
struct hns_roce_ucontext {
|
||||
struct ib_ucontext ibucontext;
|
||||
struct hns_roce_uar uar;
|
||||
};
|
||||
|
||||
struct hns_roce_pd {
|
||||
struct ib_pd ibpd;
|
||||
unsigned long pdn;
|
||||
};
|
||||
|
||||
struct hns_roce_bitmap {
|
||||
/* Bitmap Traversal last a bit which is 1 */
|
||||
unsigned long last;
|
||||
unsigned long top;
|
||||
unsigned long max;
|
||||
unsigned long reserved_top;
|
||||
unsigned long mask;
|
||||
spinlock_t lock;
|
||||
unsigned long *table;
|
||||
};
|
||||
|
||||
/* Order bitmap length -- bit num compute formula: 1 << (max_order - order) */
|
||||
/* Order = 0: bitmap is biggest, order = max bitmap is least (only a bit) */
|
||||
/* Every bit repesent to a partner free/used status in bitmap */
|
||||
/*
|
||||
* Initial, bits of other bitmap are all 0 except that a bit of max_order is 1
|
||||
* Bit = 1 represent to idle and available; bit = 0: not available
|
||||
*/
|
||||
struct hns_roce_buddy {
|
||||
/* Members point to every order level bitmap */
|
||||
unsigned long **bits;
|
||||
/* Represent to avail bits of the order level bitmap */
|
||||
u32 *num_free;
|
||||
int max_order;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/* For Hardware Entry Memory */
|
||||
struct hns_roce_hem_table {
|
||||
/* HEM type: 0 = qpc, 1 = mtt, 2 = cqc, 3 = srq, 4 = other */
|
||||
u32 type;
|
||||
/* HEM array elment num */
|
||||
unsigned long num_hem;
|
||||
/* HEM entry record obj total num */
|
||||
unsigned long num_obj;
|
||||
/*Single obj size */
|
||||
unsigned long obj_size;
|
||||
int lowmem;
|
||||
struct mutex mutex;
|
||||
struct hns_roce_hem **hem;
|
||||
};
|
||||
|
||||
struct hns_roce_mtt {
|
||||
unsigned long first_seg;
|
||||
int order;
|
||||
int page_shift;
|
||||
};
|
||||
|
||||
/* Only support 4K page size for mr register */
|
||||
#define MR_SIZE_4K 0
|
||||
|
||||
struct hns_roce_mr {
|
||||
struct ib_mr ibmr;
|
||||
struct ib_umem *umem;
|
||||
u64 iova; /* MR's virtual orignal addr */
|
||||
u64 size; /* Address range of MR */
|
||||
u32 key; /* Key of MR */
|
||||
u32 pd; /* PD num of MR */
|
||||
u32 access;/* Access permission of MR */
|
||||
int enabled; /* MR's active status */
|
||||
int type; /* MR's register type */
|
||||
u64 *pbl_buf;/* MR's PBL space */
|
||||
dma_addr_t pbl_dma_addr; /* MR's PBL space PA */
|
||||
};
|
||||
|
||||
struct hns_roce_mr_table {
|
||||
struct hns_roce_bitmap mtpt_bitmap;
|
||||
struct hns_roce_buddy mtt_buddy;
|
||||
struct hns_roce_hem_table mtt_table;
|
||||
struct hns_roce_hem_table mtpt_table;
|
||||
};
|
||||
|
||||
struct hns_roce_wq {
|
||||
u64 *wrid; /* Work request ID */
|
||||
spinlock_t lock;
|
||||
int wqe_cnt; /* WQE num */
|
||||
u32 max_post;
|
||||
int max_gs;
|
||||
int offset;
|
||||
int wqe_shift;/* WQE size */
|
||||
u32 head;
|
||||
u32 tail;
|
||||
void __iomem *db_reg_l;
|
||||
};
|
||||
|
||||
struct hns_roce_buf_list {
|
||||
void *buf;
|
||||
dma_addr_t map;
|
||||
};
|
||||
|
||||
struct hns_roce_buf {
|
||||
struct hns_roce_buf_list direct;
|
||||
struct hns_roce_buf_list *page_list;
|
||||
int nbufs;
|
||||
u32 npages;
|
||||
int page_shift;
|
||||
};
|
||||
|
||||
struct hns_roce_cq_buf {
|
||||
struct hns_roce_buf hr_buf;
|
||||
struct hns_roce_mtt hr_mtt;
|
||||
};
|
||||
|
||||
struct hns_roce_cq_resize {
|
||||
struct hns_roce_cq_buf hr_buf;
|
||||
int cqe;
|
||||
};
|
||||
|
||||
struct hns_roce_cq {
|
||||
struct ib_cq ib_cq;
|
||||
struct hns_roce_cq_buf hr_buf;
|
||||
/* pointer to store information after resize*/
|
||||
struct hns_roce_cq_resize *hr_resize_buf;
|
||||
spinlock_t lock;
|
||||
struct mutex resize_mutex;
|
||||
struct ib_umem *umem;
|
||||
struct ib_umem *resize_umem;
|
||||
void (*comp)(struct hns_roce_cq *);
|
||||
void (*event)(struct hns_roce_cq *, enum hns_roce_event);
|
||||
|
||||
struct hns_roce_uar *uar;
|
||||
u32 cq_depth;
|
||||
u32 cons_index;
|
||||
void __iomem *cq_db_l;
|
||||
void __iomem *tptr_addr;
|
||||
unsigned long cqn;
|
||||
u32 vector;
|
||||
atomic_t refcount;
|
||||
struct completion free;
|
||||
};
|
||||
|
||||
struct hns_roce_srq {
|
||||
struct ib_srq ibsrq;
|
||||
int srqn;
|
||||
};
|
||||
|
||||
struct hns_roce_uar_table {
|
||||
struct hns_roce_bitmap bitmap;
|
||||
};
|
||||
|
||||
struct hns_roce_qp_table {
|
||||
struct hns_roce_bitmap bitmap;
|
||||
spinlock_t lock;
|
||||
struct hns_roce_hem_table qp_table;
|
||||
struct hns_roce_hem_table irrl_table;
|
||||
};
|
||||
|
||||
struct hns_roce_cq_table {
|
||||
struct hns_roce_bitmap bitmap;
|
||||
spinlock_t lock;
|
||||
struct radix_tree_root tree;
|
||||
struct hns_roce_hem_table table;
|
||||
};
|
||||
|
||||
struct hns_roce_raq_table {
|
||||
struct hns_roce_buf_list *e_raq_buf;
|
||||
};
|
||||
|
||||
struct hns_roce_av {
|
||||
__le32 port_pd;
|
||||
u8 gid_index;
|
||||
u8 stat_rate;
|
||||
u8 hop_limit;
|
||||
__le32 sl_tclass_flowlabel;
|
||||
u8 dgid[HNS_ROCE_GID_SIZE];
|
||||
u8 mac[6];
|
||||
__le16 vlan;
|
||||
};
|
||||
|
||||
struct hns_roce_ah {
|
||||
struct ib_ah ibah;
|
||||
struct hns_roce_av av;
|
||||
};
|
||||
|
||||
struct hns_roce_cmd_context {
|
||||
struct completion done;
|
||||
int result;
|
||||
int next;
|
||||
u64 out_param;
|
||||
u16 token;
|
||||
};
|
||||
|
||||
struct hns_roce_cmdq {
|
||||
struct dma_pool *pool;
|
||||
u8 __iomem *hcr;
|
||||
struct mutex hcr_mutex;
|
||||
struct semaphore poll_sem;
|
||||
/*
|
||||
* Event mode: cmd register mutex protection,
|
||||
* ensure to not exceed max_cmds and user use limit region
|
||||
*/
|
||||
struct semaphore event_sem;
|
||||
int max_cmds;
|
||||
spinlock_t context_lock;
|
||||
int free_head;
|
||||
struct hns_roce_cmd_context *context;
|
||||
/*
|
||||
* Result of get integer part
|
||||
* which max_comds compute according a power of 2
|
||||
*/
|
||||
u16 token_mask;
|
||||
/*
|
||||
* Process whether use event mode, init default non-zero
|
||||
* After the event queue of cmd event ready,
|
||||
* can switch into event mode
|
||||
* close device, switch into poll mode(non event mode)
|
||||
*/
|
||||
u8 use_events;
|
||||
u8 toggle;
|
||||
};
|
||||
|
||||
struct hns_roce_dev;
|
||||
|
||||
struct hns_roce_qp {
|
||||
struct ib_qp ibqp;
|
||||
struct hns_roce_buf hr_buf;
|
||||
struct hns_roce_wq rq;
|
||||
__le64 doorbell_qpn;
|
||||
__le32 sq_signal_bits;
|
||||
u32 sq_next_wqe;
|
||||
int sq_max_wqes_per_wr;
|
||||
int sq_spare_wqes;
|
||||
struct hns_roce_wq sq;
|
||||
|
||||
struct ib_umem *umem;
|
||||
struct hns_roce_mtt mtt;
|
||||
u32 buff_size;
|
||||
struct mutex mutex;
|
||||
u8 port;
|
||||
u8 sl;
|
||||
u8 resp_depth;
|
||||
u8 state;
|
||||
u32 access_flags;
|
||||
u32 pkey_index;
|
||||
void (*event)(struct hns_roce_qp *,
|
||||
enum hns_roce_event);
|
||||
unsigned long qpn;
|
||||
|
||||
atomic_t refcount;
|
||||
struct completion free;
|
||||
};
|
||||
|
||||
struct hns_roce_sqp {
|
||||
struct hns_roce_qp hr_qp;
|
||||
};
|
||||
|
||||
struct hns_roce_ib_iboe {
|
||||
spinlock_t lock;
|
||||
struct net_device *netdevs[HNS_ROCE_MAX_PORTS];
|
||||
struct notifier_block nb;
|
||||
struct notifier_block nb_inet;
|
||||
/* 16 GID is shared by 6 port in v1 engine. */
|
||||
union ib_gid gid_table[HNS_ROCE_MAX_GID_NUM];
|
||||
u8 phy_port[HNS_ROCE_MAX_PORTS];
|
||||
};
|
||||
|
||||
struct hns_roce_eq {
|
||||
struct hns_roce_dev *hr_dev;
|
||||
void __iomem *doorbell;
|
||||
|
||||
int type_flag;/* Aeq:1 ceq:0 */
|
||||
int eqn;
|
||||
u32 entries;
|
||||
int log_entries;
|
||||
int eqe_size;
|
||||
int irq;
|
||||
int log_page_size;
|
||||
int cons_index;
|
||||
struct hns_roce_buf_list *buf_list;
|
||||
};
|
||||
|
||||
struct hns_roce_eq_table {
|
||||
struct hns_roce_eq *eq;
|
||||
void __iomem **eqc_base;
|
||||
};
|
||||
|
||||
struct hns_roce_caps {
|
||||
u8 num_ports;
|
||||
int gid_table_len[HNS_ROCE_MAX_PORTS];
|
||||
int pkey_table_len[HNS_ROCE_MAX_PORTS];
|
||||
int local_ca_ack_delay;
|
||||
int num_uars;
|
||||
u32 phy_num_uars;
|
||||
u32 max_sq_sg; /* 2 */
|
||||
u32 max_sq_inline; /* 32 */
|
||||
u32 max_rq_sg; /* 2 */
|
||||
int num_qps; /* 256k */
|
||||
u32 max_wqes; /* 16k */
|
||||
u32 max_sq_desc_sz; /* 64 */
|
||||
u32 max_rq_desc_sz; /* 64 */
|
||||
int max_qp_init_rdma;
|
||||
int max_qp_dest_rdma;
|
||||
int sqp_start;
|
||||
int num_cqs;
|
||||
int max_cqes;
|
||||
int reserved_cqs;
|
||||
int num_aeq_vectors; /* 1 */
|
||||
int num_comp_vectors; /* 32 ceq */
|
||||
int num_other_vectors;
|
||||
int num_mtpts;
|
||||
u32 num_mtt_segs;
|
||||
int reserved_mrws;
|
||||
int reserved_uars;
|
||||
int num_pds;
|
||||
int reserved_pds;
|
||||
u32 mtt_entry_sz;
|
||||
u32 cq_entry_sz;
|
||||
u32 page_size_cap;
|
||||
u32 reserved_lkey;
|
||||
int mtpt_entry_sz;
|
||||
int qpc_entry_sz;
|
||||
int irrl_entry_sz;
|
||||
int cqc_entry_sz;
|
||||
int aeqe_depth;
|
||||
int ceqe_depth[HNS_ROCE_COMP_VEC_NUM];
|
||||
enum ib_mtu max_mtu;
|
||||
};
|
||||
|
||||
struct hns_roce_hw {
|
||||
int (*reset)(struct hns_roce_dev *hr_dev, bool enable);
|
||||
void (*hw_profile)(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 (*set_gid)(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
|
||||
union ib_gid *gid);
|
||||
void (*set_mac)(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr);
|
||||
void (*set_mtu)(struct hns_roce_dev *hr_dev, u8 phy_port,
|
||||
enum ib_mtu mtu);
|
||||
int (*write_mtpt)(void *mb_buf, struct hns_roce_mr *mr,
|
||||
unsigned long mtpt_idx);
|
||||
void (*write_cqc)(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts,
|
||||
dma_addr_t dma_handle, int nent, u32 vector);
|
||||
int (*query_qp)(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
|
||||
int (*modify_qp)(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
int attr_mask, enum ib_qp_state cur_state,
|
||||
enum ib_qp_state new_state);
|
||||
int (*destroy_qp)(struct ib_qp *ibqp);
|
||||
int (*post_send)(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
struct ib_send_wr **bad_wr);
|
||||
int (*post_recv)(struct ib_qp *qp, struct ib_recv_wr *recv_wr,
|
||||
struct ib_recv_wr **bad_recv_wr);
|
||||
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);
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct hns_roce_dev {
|
||||
struct ib_device ib_dev;
|
||||
struct platform_device *pdev;
|
||||
struct hns_roce_uar priv_uar;
|
||||
const char *irq_names;
|
||||
spinlock_t sm_lock;
|
||||
spinlock_t cq_db_lock;
|
||||
spinlock_t bt_cmd_lock;
|
||||
struct hns_roce_ib_iboe iboe;
|
||||
|
||||
int irq[HNS_ROCE_MAX_IRQ_NUM];
|
||||
u8 __iomem *reg_base;
|
||||
struct hns_roce_caps caps;
|
||||
struct radix_tree_root qp_table_tree;
|
||||
|
||||
unsigned char dev_addr[HNS_ROCE_MAX_PORTS][MAC_ADDR_OCTET_NUM];
|
||||
u64 sys_image_guid;
|
||||
u32 vendor_id;
|
||||
u32 vendor_part_id;
|
||||
u32 hw_rev;
|
||||
void __iomem *priv_addr;
|
||||
|
||||
struct hns_roce_cmdq cmd;
|
||||
struct hns_roce_bitmap pd_bitmap;
|
||||
struct hns_roce_uar_table uar_table;
|
||||
struct hns_roce_mr_table mr_table;
|
||||
struct hns_roce_cq_table cq_table;
|
||||
struct hns_roce_qp_table qp_table;
|
||||
struct hns_roce_eq_table eq_table;
|
||||
|
||||
int cmd_mod;
|
||||
int loop_idc;
|
||||
struct hns_roce_hw *hw;
|
||||
};
|
||||
|
||||
static inline struct hns_roce_dev *to_hr_dev(struct ib_device *ib_dev)
|
||||
{
|
||||
return container_of(ib_dev, struct hns_roce_dev, ib_dev);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_ucontext
|
||||
*to_hr_ucontext(struct ib_ucontext *ibucontext)
|
||||
{
|
||||
return container_of(ibucontext, struct hns_roce_ucontext, ibucontext);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_pd *to_hr_pd(struct ib_pd *ibpd)
|
||||
{
|
||||
return container_of(ibpd, struct hns_roce_pd, ibpd);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_ah *to_hr_ah(struct ib_ah *ibah)
|
||||
{
|
||||
return container_of(ibah, struct hns_roce_ah, ibah);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_mr *to_hr_mr(struct ib_mr *ibmr)
|
||||
{
|
||||
return container_of(ibmr, struct hns_roce_mr, ibmr);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_qp *to_hr_qp(struct ib_qp *ibqp)
|
||||
{
|
||||
return container_of(ibqp, struct hns_roce_qp, ibqp);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_cq *to_hr_cq(struct ib_cq *ib_cq)
|
||||
{
|
||||
return container_of(ib_cq, struct hns_roce_cq, ib_cq);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_srq *to_hr_srq(struct ib_srq *ibsrq)
|
||||
{
|
||||
return container_of(ibsrq, struct hns_roce_srq, ibsrq);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_sqp *hr_to_hr_sqp(struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
return container_of(hr_qp, struct hns_roce_sqp, hr_qp);
|
||||
}
|
||||
|
||||
static inline void hns_roce_write64_k(__be32 val[2], void __iomem *dest)
|
||||
{
|
||||
__raw_writeq(*(u64 *) val, dest);
|
||||
}
|
||||
|
||||
static inline struct hns_roce_qp
|
||||
*__hns_roce_qp_lookup(struct hns_roce_dev *hr_dev, u32 qpn)
|
||||
{
|
||||
return radix_tree_lookup(&hr_dev->qp_table_tree,
|
||||
qpn & (hr_dev->caps.num_qps - 1));
|
||||
}
|
||||
|
||||
static inline void *hns_roce_buf_offset(struct hns_roce_buf *buf, int offset)
|
||||
{
|
||||
u32 bits_per_long_val = BITS_PER_LONG;
|
||||
|
||||
if (bits_per_long_val == 64 || buf->nbufs == 1)
|
||||
return (char *)(buf->direct.buf) + offset;
|
||||
else
|
||||
return (char *)(buf->page_list[offset >> PAGE_SHIFT].buf) +
|
||||
(offset & (PAGE_SIZE - 1));
|
||||
}
|
||||
|
||||
int hns_roce_init_uar_table(struct hns_roce_dev *dev);
|
||||
int hns_roce_uar_alloc(struct hns_roce_dev *dev, struct hns_roce_uar *uar);
|
||||
void hns_roce_uar_free(struct hns_roce_dev *dev, struct hns_roce_uar *uar);
|
||||
void hns_roce_cleanup_uar_table(struct hns_roce_dev *dev);
|
||||
|
||||
int hns_roce_cmd_init(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cmd_cleanup(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cmd_event(struct hns_roce_dev *hr_dev, u16 token, u8 status,
|
||||
u64 out_param);
|
||||
int hns_roce_cmd_use_events(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev);
|
||||
|
||||
int hns_roce_mtt_init(struct hns_roce_dev *hr_dev, int npages, int page_shift,
|
||||
struct hns_roce_mtt *mtt);
|
||||
void hns_roce_mtt_cleanup(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt);
|
||||
int hns_roce_buf_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, struct hns_roce_buf *buf);
|
||||
|
||||
int hns_roce_init_pd_table(struct hns_roce_dev *hr_dev);
|
||||
int hns_roce_init_mr_table(struct hns_roce_dev *hr_dev);
|
||||
int hns_roce_init_eq_table(struct hns_roce_dev *hr_dev);
|
||||
int hns_roce_init_cq_table(struct hns_roce_dev *hr_dev);
|
||||
int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev);
|
||||
|
||||
void hns_roce_cleanup_pd_table(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cleanup_mr_table(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cleanup_eq_table(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cleanup_cq_table(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev);
|
||||
|
||||
int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj);
|
||||
void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj);
|
||||
int hns_roce_bitmap_init(struct hns_roce_bitmap *bitmap, u32 num, u32 mask,
|
||||
u32 reserved_bot, u32 resetrved_top);
|
||||
void hns_roce_bitmap_cleanup(struct hns_roce_bitmap *bitmap);
|
||||
void hns_roce_cleanup_bitmap(struct hns_roce_dev *hr_dev);
|
||||
int hns_roce_bitmap_alloc_range(struct hns_roce_bitmap *bitmap, int cnt,
|
||||
int align, unsigned long *obj);
|
||||
void hns_roce_bitmap_free_range(struct hns_roce_bitmap *bitmap,
|
||||
unsigned long obj, int cnt);
|
||||
|
||||
struct ib_ah *hns_roce_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
|
||||
int hns_roce_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr);
|
||||
int hns_roce_destroy_ah(struct ib_ah *ah);
|
||||
|
||||
struct ib_pd *hns_roce_alloc_pd(struct ib_device *ib_dev,
|
||||
struct ib_ucontext *context,
|
||||
struct ib_udata *udata);
|
||||
int hns_roce_dealloc_pd(struct ib_pd *pd);
|
||||
|
||||
struct ib_mr *hns_roce_get_dma_mr(struct ib_pd *pd, int acc);
|
||||
struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
u64 virt_addr, int access_flags,
|
||||
struct ib_udata *udata);
|
||||
int hns_roce_dereg_mr(struct ib_mr *ibmr);
|
||||
|
||||
void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size,
|
||||
struct hns_roce_buf *buf);
|
||||
int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
|
||||
struct hns_roce_buf *buf);
|
||||
|
||||
int hns_roce_ib_umem_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, struct ib_umem *umem);
|
||||
|
||||
struct ib_qp *hns_roce_create_qp(struct ib_pd *ib_pd,
|
||||
struct ib_qp_init_attr *init_attr,
|
||||
struct ib_udata *udata);
|
||||
int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
int attr_mask, struct ib_udata *udata);
|
||||
void *get_recv_wqe(struct hns_roce_qp *hr_qp, int n);
|
||||
void *get_send_wqe(struct hns_roce_qp *hr_qp, int n);
|
||||
bool hns_roce_wq_overflow(struct hns_roce_wq *hr_wq, int nreq,
|
||||
struct ib_cq *ib_cq);
|
||||
enum hns_roce_qp_state to_hns_roce_state(enum ib_qp_state state);
|
||||
void hns_roce_lock_cqs(struct hns_roce_cq *send_cq,
|
||||
struct hns_roce_cq *recv_cq);
|
||||
void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq,
|
||||
struct hns_roce_cq *recv_cq);
|
||||
void hns_roce_qp_remove(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
|
||||
void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
|
||||
void hns_roce_release_range_qp(struct hns_roce_dev *hr_dev, int base_qpn,
|
||||
int cnt);
|
||||
__be32 send_ieth(struct ib_send_wr *wr);
|
||||
int to_hr_qp_type(int qp_type);
|
||||
|
||||
struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
|
||||
const struct ib_cq_init_attr *attr,
|
||||
struct ib_ucontext *context,
|
||||
struct ib_udata *udata);
|
||||
|
||||
int hns_roce_ib_destroy_cq(struct ib_cq *ib_cq);
|
||||
|
||||
void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
|
||||
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
|
||||
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type);
|
||||
int hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index);
|
||||
|
||||
extern struct hns_roce_hw hns_roce_hw_v1;
|
||||
|
||||
#endif /* _HNS_ROCE_DEVICE_H */
|
|
@ -0,0 +1,762 @@
|
|||
/*
|
||||
* 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 "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;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
hns_roce_qp_event(hr_dev, 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),
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
hns_roce_qp_event(hr_dev, 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),
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S));
|
||||
}
|
||||
|
||||
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 qpn = 0;
|
||||
|
||||
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();
|
||||
|
||||
switch (roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S)) {
|
||||
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:
|
||||
dev_warn(dev, "qpn = 0x%lx\n",
|
||||
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));
|
||||
hns_roce_qp_event(hr_dev,
|
||||
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),
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S));
|
||||
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;
|
||||
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:
|
||||
dev_warn(dev, "CQ 0x%lx access err.\n",
|
||||
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));
|
||||
hns_roce_cq_event(hr_dev,
|
||||
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)),
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S));
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW:
|
||||
dev_warn(dev, "CQ 0x%lx overflow\n",
|
||||
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));
|
||||
hns_roce_cq_event(hr_dev,
|
||||
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)),
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S));
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID:
|
||||
dev_warn(dev, "CQ ID invalid.\n");
|
||||
hns_roce_cq_event(hr_dev,
|
||||
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)),
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S));
|
||||
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 0x%lx on EQ %d at index %u\n",
|
||||
roce_get_field(aeqe->asyn,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_M,
|
||||
HNS_ROCE_AEQE_U32_4_EVENT_TYPE_S),
|
||||
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), (u8 *)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, (u8 *)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, (u8 *)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, 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);
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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_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 */
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Hisilicon Limited.
|
||||
* Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* 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 "hns_roce_device.h"
|
||||
#include "hns_roce_hem.h"
|
||||
#include "hns_roce_common.h"
|
||||
|
||||
#define HW_SYNC_TIMEOUT_MSECS 500
|
||||
#define HW_SYNC_SLEEP_TIME_INTERVAL 20
|
||||
|
||||
#define HNS_ROCE_HEM_ALLOC_SIZE (1 << 17)
|
||||
#define HNS_ROCE_TABLE_CHUNK_SIZE (1 << 17)
|
||||
|
||||
#define DMA_ADDR_T_SHIFT 12
|
||||
#define BT_CMD_SYNC_SHIFT 31
|
||||
#define BT_BA_SHIFT 32
|
||||
|
||||
struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, int npages,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk = NULL;
|
||||
struct hns_roce_hem *hem;
|
||||
struct scatterlist *mem;
|
||||
int order;
|
||||
void *buf;
|
||||
|
||||
WARN_ON(gfp_mask & __GFP_HIGHMEM);
|
||||
|
||||
hem = kmalloc(sizeof(*hem),
|
||||
gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
|
||||
if (!hem)
|
||||
return NULL;
|
||||
|
||||
hem->refcount = 0;
|
||||
INIT_LIST_HEAD(&hem->chunk_list);
|
||||
|
||||
order = get_order(HNS_ROCE_HEM_ALLOC_SIZE);
|
||||
|
||||
while (npages > 0) {
|
||||
if (!chunk) {
|
||||
chunk = kmalloc(sizeof(*chunk),
|
||||
gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
|
||||
if (!chunk)
|
||||
goto fail;
|
||||
|
||||
sg_init_table(chunk->mem, HNS_ROCE_HEM_CHUNK_LEN);
|
||||
chunk->npages = 0;
|
||||
chunk->nsg = 0;
|
||||
list_add_tail(&chunk->list, &hem->chunk_list);
|
||||
}
|
||||
|
||||
while (1 << order > npages)
|
||||
--order;
|
||||
|
||||
/*
|
||||
* Alloc memory one time. If failed, don't alloc small block
|
||||
* memory, directly return fail.
|
||||
*/
|
||||
mem = &chunk->mem[chunk->npages];
|
||||
buf = dma_alloc_coherent(&hr_dev->pdev->dev, PAGE_SIZE << order,
|
||||
&sg_dma_address(mem), gfp_mask);
|
||||
if (!buf)
|
||||
goto fail;
|
||||
|
||||
sg_set_buf(mem, buf, PAGE_SIZE << order);
|
||||
WARN_ON(mem->offset);
|
||||
sg_dma_len(mem) = PAGE_SIZE << order;
|
||||
|
||||
++chunk->npages;
|
||||
++chunk->nsg;
|
||||
npages -= 1 << order;
|
||||
}
|
||||
|
||||
return hem;
|
||||
|
||||
fail:
|
||||
hns_roce_free_hem(hr_dev, hem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk, *tmp;
|
||||
int i;
|
||||
|
||||
if (!hem)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) {
|
||||
for (i = 0; i < chunk->npages; ++i)
|
||||
dma_free_coherent(&hr_dev->pdev->dev,
|
||||
chunk->mem[i].length,
|
||||
lowmem_page_address(sg_page(&chunk->mem[i])),
|
||||
sg_dma_address(&chunk->mem[i]));
|
||||
kfree(chunk);
|
||||
}
|
||||
|
||||
kfree(hem);
|
||||
}
|
||||
|
||||
static int hns_roce_set_hem(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
spinlock_t *lock = &hr_dev->bt_cmd_lock;
|
||||
unsigned long end = 0;
|
||||
unsigned long flags;
|
||||
struct hns_roce_hem_iter iter;
|
||||
void __iomem *bt_cmd;
|
||||
u32 bt_cmd_h_val = 0;
|
||||
u32 bt_cmd_val[2];
|
||||
u32 bt_cmd_l = 0;
|
||||
u64 bt_ba = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Find the HEM(Hardware Entry Memory) entry */
|
||||
unsigned long i = (obj & (table->num_obj - 1)) /
|
||||
(HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size);
|
||||
|
||||
switch (table->type) {
|
||||
case HEM_TYPE_QPC:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_QPC);
|
||||
break;
|
||||
case HEM_TYPE_MTPT:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
|
||||
HEM_TYPE_MTPT);
|
||||
break;
|
||||
case HEM_TYPE_CQC:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_CQC);
|
||||
break;
|
||||
case HEM_TYPE_SRQC:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
|
||||
HEM_TYPE_SRQC);
|
||||
break;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S, obj);
|
||||
roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S, 0);
|
||||
roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S, 1);
|
||||
|
||||
/* Currently iter only a chunk */
|
||||
for (hns_roce_hem_first(table->hem[i], &iter);
|
||||
!hns_roce_hem_last(&iter); hns_roce_hem_next(&iter)) {
|
||||
bt_ba = hns_roce_hem_addr(&iter) >> DMA_ADDR_T_SHIFT;
|
||||
|
||||
spin_lock_irqsave(lock, flags);
|
||||
|
||||
bt_cmd = hr_dev->reg_base + ROCEE_BT_CMD_H_REG;
|
||||
|
||||
end = msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS) + jiffies;
|
||||
while (1) {
|
||||
if (readl(bt_cmd) >> BT_CMD_SYNC_SHIFT) {
|
||||
if (!(time_before(jiffies, end))) {
|
||||
dev_err(dev, "Write bt_cmd err,hw_sync is not zero.\n");
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
msleep(HW_SYNC_SLEEP_TIME_INTERVAL);
|
||||
}
|
||||
|
||||
bt_cmd_l = (u32)bt_ba;
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S,
|
||||
bt_ba >> BT_BA_SHIFT);
|
||||
|
||||
bt_cmd_val[0] = bt_cmd_l;
|
||||
bt_cmd_val[1] = bt_cmd_h_val;
|
||||
hns_roce_write64_k(bt_cmd_val,
|
||||
hr_dev->reg_base + ROCEE_BT_CMD_L_REG);
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_clear_hem(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
unsigned long end = 0;
|
||||
unsigned long flags;
|
||||
void __iomem *bt_cmd;
|
||||
uint32_t bt_cmd_val[2];
|
||||
u32 bt_cmd_h_val = 0;
|
||||
int ret = 0;
|
||||
|
||||
switch (table->type) {
|
||||
case HEM_TYPE_QPC:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_QPC);
|
||||
break;
|
||||
case HEM_TYPE_MTPT:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
|
||||
HEM_TYPE_MTPT);
|
||||
break;
|
||||
case HEM_TYPE_CQC:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_CQC);
|
||||
break;
|
||||
case HEM_TYPE_SRQC:
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
|
||||
HEM_TYPE_SRQC);
|
||||
break;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S, obj);
|
||||
roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S, 0);
|
||||
roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S, 1);
|
||||
roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M,
|
||||
ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S, 0);
|
||||
|
||||
spin_lock_irqsave(&hr_dev->bt_cmd_lock, flags);
|
||||
|
||||
bt_cmd = hr_dev->reg_base + ROCEE_BT_CMD_H_REG;
|
||||
|
||||
end = msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS) + jiffies;
|
||||
while (1) {
|
||||
if (readl(bt_cmd) >> BT_CMD_SYNC_SHIFT) {
|
||||
if (!(time_before(jiffies, end))) {
|
||||
dev_err(dev, "Write bt_cmd err,hw_sync is not zero.\n");
|
||||
spin_unlock_irqrestore(&hr_dev->bt_cmd_lock,
|
||||
flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
msleep(HW_SYNC_SLEEP_TIME_INTERVAL);
|
||||
}
|
||||
|
||||
bt_cmd_val[0] = 0;
|
||||
bt_cmd_val[1] = bt_cmd_h_val;
|
||||
hns_roce_write64_k(bt_cmd_val, hr_dev->reg_base + ROCEE_BT_CMD_L_REG);
|
||||
spin_unlock_irqrestore(&hr_dev->bt_cmd_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
int ret = 0;
|
||||
unsigned long i;
|
||||
|
||||
i = (obj & (table->num_obj - 1)) / (HNS_ROCE_TABLE_CHUNK_SIZE /
|
||||
table->obj_size);
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
|
||||
if (table->hem[i]) {
|
||||
++table->hem[i]->refcount;
|
||||
goto out;
|
||||
}
|
||||
|
||||
table->hem[i] = hns_roce_alloc_hem(hr_dev,
|
||||
HNS_ROCE_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
|
||||
(table->lowmem ? GFP_KERNEL :
|
||||
GFP_HIGHUSER) | __GFP_NOWARN);
|
||||
if (!table->hem[i]) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set HEM base address(128K/page, pa) to Hardware */
|
||||
if (hns_roce_set_hem(hr_dev, table, obj)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "set HEM base address to HW failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
++table->hem[i]->refcount;
|
||||
out:
|
||||
mutex_unlock(&table->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
unsigned long i;
|
||||
|
||||
i = (obj & (table->num_obj - 1)) /
|
||||
(HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size);
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
|
||||
if (--table->hem[i]->refcount == 0) {
|
||||
/* Clear HEM base address */
|
||||
if (hns_roce_clear_hem(hr_dev, table, obj))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
hns_roce_free_hem(hr_dev, table->hem[i]);
|
||||
table->hem[i] = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&table->mutex);
|
||||
}
|
||||
|
||||
void *hns_roce_table_find(struct hns_roce_hem_table *table, unsigned long obj,
|
||||
dma_addr_t *dma_handle)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk;
|
||||
unsigned long idx;
|
||||
int i;
|
||||
int offset, dma_offset;
|
||||
struct hns_roce_hem *hem;
|
||||
struct page *page = NULL;
|
||||
|
||||
if (!table->lowmem)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
idx = (obj & (table->num_obj - 1)) * table->obj_size;
|
||||
hem = table->hem[idx / HNS_ROCE_TABLE_CHUNK_SIZE];
|
||||
dma_offset = offset = idx % HNS_ROCE_TABLE_CHUNK_SIZE;
|
||||
|
||||
if (!hem)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(chunk, &hem->chunk_list, list) {
|
||||
for (i = 0; i < chunk->npages; ++i) {
|
||||
if (dma_handle && dma_offset >= 0) {
|
||||
if (sg_dma_len(&chunk->mem[i]) >
|
||||
(u32)dma_offset)
|
||||
*dma_handle = sg_dma_address(
|
||||
&chunk->mem[i]) + dma_offset;
|
||||
dma_offset -= sg_dma_len(&chunk->mem[i]);
|
||||
}
|
||||
|
||||
if (chunk->mem[i].length > (u32)offset) {
|
||||
page = sg_page(&chunk->mem[i]);
|
||||
goto out;
|
||||
}
|
||||
offset -= chunk->mem[i].length;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&table->mutex);
|
||||
return page ? lowmem_page_address(page) + offset : NULL;
|
||||
}
|
||||
|
||||
int hns_roce_table_get_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned long inc = HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size;
|
||||
unsigned long i = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Allocate MTT entry memory according to chunk(128K) */
|
||||
for (i = start; i <= end; i += inc) {
|
||||
ret = hns_roce_table_get(hr_dev, table, i);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
while (i > start) {
|
||||
i -= inc;
|
||||
hns_roce_table_put(hr_dev, table, i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_table_put_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = start; i <= end;
|
||||
i += HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size)
|
||||
hns_roce_table_put(hr_dev, table, i);
|
||||
}
|
||||
|
||||
int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, u32 type,
|
||||
unsigned long obj_size, unsigned long nobj,
|
||||
int use_lowmem)
|
||||
{
|
||||
unsigned long obj_per_chunk;
|
||||
unsigned long num_hem;
|
||||
|
||||
obj_per_chunk = HNS_ROCE_TABLE_CHUNK_SIZE / obj_size;
|
||||
num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
|
||||
|
||||
table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
|
||||
if (!table->hem)
|
||||
return -ENOMEM;
|
||||
|
||||
table->type = type;
|
||||
table->num_hem = num_hem;
|
||||
table->num_obj = nobj;
|
||||
table->obj_size = obj_size;
|
||||
table->lowmem = use_lowmem;
|
||||
mutex_init(&table->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < table->num_hem; ++i)
|
||||
if (table->hem[i]) {
|
||||
if (hns_roce_clear_hem(hr_dev, table,
|
||||
i * HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size))
|
||||
dev_err(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
hns_roce_free_hem(hr_dev, table->hem[i]);
|
||||
}
|
||||
|
||||
kfree(table->hem);
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->cq_table.table);
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.irrl_table);
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.qp_table);
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table);
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table);
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Hisilicon Limited.
|
||||
* Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* 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_HEM_H
|
||||
#define _HNS_ROCE_HEM_H
|
||||
|
||||
enum {
|
||||
/* MAP HEM(Hardware Entry Memory) */
|
||||
HEM_TYPE_QPC = 0,
|
||||
HEM_TYPE_MTPT,
|
||||
HEM_TYPE_CQC,
|
||||
HEM_TYPE_SRQC,
|
||||
|
||||
/* UNMAP HEM */
|
||||
HEM_TYPE_MTT,
|
||||
HEM_TYPE_IRRL,
|
||||
};
|
||||
|
||||
#define HNS_ROCE_HEM_CHUNK_LEN \
|
||||
((256 - sizeof(struct list_head) - 2 * sizeof(int)) / \
|
||||
(sizeof(struct scatterlist)))
|
||||
|
||||
enum {
|
||||
HNS_ROCE_HEM_PAGE_SHIFT = 12,
|
||||
HNS_ROCE_HEM_PAGE_SIZE = 1 << HNS_ROCE_HEM_PAGE_SHIFT,
|
||||
};
|
||||
|
||||
struct hns_roce_hem_chunk {
|
||||
struct list_head list;
|
||||
int npages;
|
||||
int nsg;
|
||||
struct scatterlist mem[HNS_ROCE_HEM_CHUNK_LEN];
|
||||
};
|
||||
|
||||
struct hns_roce_hem {
|
||||
struct list_head chunk_list;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
struct hns_roce_hem_iter {
|
||||
struct hns_roce_hem *hem;
|
||||
struct hns_roce_hem_chunk *chunk;
|
||||
int page_idx;
|
||||
};
|
||||
|
||||
void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem);
|
||||
int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj);
|
||||
void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj);
|
||||
void *hns_roce_table_find(struct hns_roce_hem_table *table, unsigned long obj,
|
||||
dma_addr_t *dma_handle);
|
||||
int hns_roce_table_get_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long start, unsigned long end);
|
||||
void hns_roce_table_put_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long start, unsigned long end);
|
||||
int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, u32 type,
|
||||
unsigned long obj_size, unsigned long nobj,
|
||||
int use_lowmem);
|
||||
void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table);
|
||||
void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev);
|
||||
|
||||
static inline void hns_roce_hem_first(struct hns_roce_hem *hem,
|
||||
struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
iter->hem = hem;
|
||||
iter->chunk = list_empty(&hem->chunk_list) ? NULL :
|
||||
list_entry(hem->chunk_list.next,
|
||||
struct hns_roce_hem_chunk, list);
|
||||
iter->page_idx = 0;
|
||||
}
|
||||
|
||||
static inline int hns_roce_hem_last(struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
return !iter->chunk;
|
||||
}
|
||||
|
||||
static inline void hns_roce_hem_next(struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
if (++iter->page_idx >= iter->chunk->nsg) {
|
||||
if (iter->chunk->list.next == &iter->hem->chunk_list) {
|
||||
iter->chunk = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
iter->chunk = list_entry(iter->chunk->list.next,
|
||||
struct hns_roce_hem_chunk, list);
|
||||
iter->page_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline dma_addr_t hns_roce_hem_addr(struct hns_roce_hem_iter *iter)
|
||||
{
|
||||
return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
|
||||
}
|
||||
|
||||
#endif /*_HNS_ROCE_HEM_H*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,981 @@
|
|||
/*
|
||||
* 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_HW_V1_H
|
||||
#define _HNS_ROCE_HW_V1_H
|
||||
|
||||
#define CQ_STATE_VALID 2
|
||||
|
||||
#define HNS_ROCE_V1_MAX_PD_NUM 0x8000
|
||||
#define HNS_ROCE_V1_MAX_CQ_NUM 0x10000
|
||||
#define HNS_ROCE_V1_MAX_CQE_NUM 0x8000
|
||||
|
||||
#define HNS_ROCE_V1_MAX_QP_NUM 0x40000
|
||||
#define HNS_ROCE_V1_MAX_WQE_NUM 0x4000
|
||||
|
||||
#define HNS_ROCE_V1_MAX_MTPT_NUM 0x80000
|
||||
|
||||
#define HNS_ROCE_V1_MAX_MTT_SEGS 0x100000
|
||||
|
||||
#define HNS_ROCE_V1_MAX_QP_INIT_RDMA 128
|
||||
#define HNS_ROCE_V1_MAX_QP_DEST_RDMA 128
|
||||
|
||||
#define HNS_ROCE_V1_MAX_SQ_DESC_SZ 64
|
||||
#define HNS_ROCE_V1_MAX_RQ_DESC_SZ 64
|
||||
#define HNS_ROCE_V1_SG_NUM 2
|
||||
#define HNS_ROCE_V1_INLINE_SIZE 32
|
||||
|
||||
#define HNS_ROCE_V1_UAR_NUM 256
|
||||
#define HNS_ROCE_V1_PHY_UAR_NUM 8
|
||||
|
||||
#define HNS_ROCE_V1_GID_NUM 16
|
||||
|
||||
#define HNS_ROCE_V1_NUM_COMP_EQE 0x8000
|
||||
#define HNS_ROCE_V1_NUM_ASYNC_EQE 0x400
|
||||
|
||||
#define HNS_ROCE_V1_QPC_ENTRY_SIZE 256
|
||||
#define HNS_ROCE_V1_IRRL_ENTRY_SIZE 8
|
||||
#define HNS_ROCE_V1_CQC_ENTRY_SIZE 64
|
||||
#define HNS_ROCE_V1_MTPT_ENTRY_SIZE 64
|
||||
#define HNS_ROCE_V1_MTT_ENTRY_SIZE 64
|
||||
|
||||
#define HNS_ROCE_V1_CQE_ENTRY_SIZE 32
|
||||
#define HNS_ROCE_V1_PAGE_SIZE_SUPPORT 0xFFFFF000
|
||||
|
||||
#define HNS_ROCE_V1_EXT_RAQ_WF 8
|
||||
#define HNS_ROCE_V1_RAQ_ENTRY 64
|
||||
#define HNS_ROCE_V1_RAQ_DEPTH 32768
|
||||
#define HNS_ROCE_V1_RAQ_SIZE (HNS_ROCE_V1_RAQ_ENTRY * HNS_ROCE_V1_RAQ_DEPTH)
|
||||
|
||||
#define HNS_ROCE_V1_SDB_DEPTH 0x400
|
||||
#define HNS_ROCE_V1_ODB_DEPTH 0x400
|
||||
|
||||
#define HNS_ROCE_V1_DB_RSVD 0x80
|
||||
|
||||
#define HNS_ROCE_V1_SDB_ALEPT HNS_ROCE_V1_DB_RSVD
|
||||
#define HNS_ROCE_V1_SDB_ALFUL (HNS_ROCE_V1_SDB_DEPTH - HNS_ROCE_V1_DB_RSVD)
|
||||
#define HNS_ROCE_V1_ODB_ALEPT HNS_ROCE_V1_DB_RSVD
|
||||
#define HNS_ROCE_V1_ODB_ALFUL (HNS_ROCE_V1_ODB_DEPTH - HNS_ROCE_V1_DB_RSVD)
|
||||
|
||||
#define HNS_ROCE_V1_EXT_SDB_DEPTH 0x4000
|
||||
#define HNS_ROCE_V1_EXT_ODB_DEPTH 0x4000
|
||||
#define HNS_ROCE_V1_EXT_SDB_ENTRY 16
|
||||
#define HNS_ROCE_V1_EXT_ODB_ENTRY 16
|
||||
#define HNS_ROCE_V1_EXT_SDB_SIZE \
|
||||
(HNS_ROCE_V1_EXT_SDB_DEPTH * HNS_ROCE_V1_EXT_SDB_ENTRY)
|
||||
#define HNS_ROCE_V1_EXT_ODB_SIZE \
|
||||
(HNS_ROCE_V1_EXT_ODB_DEPTH * HNS_ROCE_V1_EXT_ODB_ENTRY)
|
||||
|
||||
#define HNS_ROCE_V1_EXT_SDB_ALEPT HNS_ROCE_V1_DB_RSVD
|
||||
#define HNS_ROCE_V1_EXT_SDB_ALFUL \
|
||||
(HNS_ROCE_V1_EXT_SDB_DEPTH - HNS_ROCE_V1_DB_RSVD)
|
||||
#define HNS_ROCE_V1_EXT_ODB_ALEPT HNS_ROCE_V1_DB_RSVD
|
||||
#define HNS_ROCE_V1_EXT_ODB_ALFUL \
|
||||
(HNS_ROCE_V1_EXT_ODB_DEPTH - HNS_ROCE_V1_DB_RSVD)
|
||||
|
||||
#define HNS_ROCE_ODB_POLL_MODE 0
|
||||
|
||||
#define HNS_ROCE_SDB_NORMAL_MODE 0
|
||||
#define HNS_ROCE_SDB_EXTEND_MODE 1
|
||||
|
||||
#define HNS_ROCE_ODB_EXTEND_MODE 1
|
||||
|
||||
#define KEY_VALID 0x02
|
||||
|
||||
#define HNS_ROCE_CQE_QPN_MASK 0x3ffff
|
||||
#define HNS_ROCE_CQE_STATUS_MASK 0x1f
|
||||
#define HNS_ROCE_CQE_OPCODE_MASK 0xf
|
||||
|
||||
#define HNS_ROCE_CQE_SUCCESS 0x00
|
||||
#define HNS_ROCE_CQE_SYNDROME_LOCAL_LENGTH_ERR 0x01
|
||||
#define HNS_ROCE_CQE_SYNDROME_LOCAL_QP_OP_ERR 0x02
|
||||
#define HNS_ROCE_CQE_SYNDROME_LOCAL_PROT_ERR 0x03
|
||||
#define HNS_ROCE_CQE_SYNDROME_WR_FLUSH_ERR 0x04
|
||||
#define HNS_ROCE_CQE_SYNDROME_MEM_MANAGE_OPERATE_ERR 0x05
|
||||
#define HNS_ROCE_CQE_SYNDROME_BAD_RESP_ERR 0x06
|
||||
#define HNS_ROCE_CQE_SYNDROME_LOCAL_ACCESS_ERR 0x07
|
||||
#define HNS_ROCE_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR 0x08
|
||||
#define HNS_ROCE_CQE_SYNDROME_REMOTE_ACCESS_ERR 0x09
|
||||
#define HNS_ROCE_CQE_SYNDROME_REMOTE_OP_ERR 0x0a
|
||||
#define HNS_ROCE_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR 0x0b
|
||||
#define HNS_ROCE_CQE_SYNDROME_RNR_RETRY_EXC_ERR 0x0c
|
||||
|
||||
#define QP1C_CFGN_OFFSET 0x28
|
||||
#define PHY_PORT_OFFSET 0x8
|
||||
#define MTPT_IDX_SHIFT 16
|
||||
#define ALL_PORT_VAL_OPEN 0x3f
|
||||
#define POL_TIME_INTERVAL_VAL 0x80
|
||||
#define SLEEP_TIME_INTERVAL 20
|
||||
#define SQ_PSN_SHIFT 8
|
||||
#define QKEY_VAL 0x80010000
|
||||
#define SDB_INV_CNT_OFFSET 8
|
||||
|
||||
struct hns_roce_cq_context {
|
||||
u32 cqc_byte_4;
|
||||
u32 cq_bt_l;
|
||||
u32 cqc_byte_12;
|
||||
u32 cur_cqe_ba0_l;
|
||||
u32 cqc_byte_20;
|
||||
u32 cqe_tptr_addr_l;
|
||||
u32 cur_cqe_ba1_l;
|
||||
u32 cqc_byte_32;
|
||||
};
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_4_CQC_STATE_S 0
|
||||
#define CQ_CONTEXT_CQC_BYTE_4_CQC_STATE_M \
|
||||
(((1UL << 2) - 1) << CQ_CONTEXT_CQC_BYTE_4_CQC_STATE_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_4_CQN_S 16
|
||||
#define CQ_CONTEXT_CQC_BYTE_4_CQN_M \
|
||||
(((1UL << 16) - 1) << CQ_CONTEXT_CQC_BYTE_4_CQN_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_12_CQ_BT_H_S 0
|
||||
#define CQ_CONTEXT_CQC_BYTE_12_CQ_BT_H_M \
|
||||
(((1UL << 17) - 1) << CQ_CONTEXT_CQC_BYTE_12_CQ_BT_H_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_12_CQ_CQE_SHIFT_S 20
|
||||
#define CQ_CONTEXT_CQC_BYTE_12_CQ_CQE_SHIFT_M \
|
||||
(((1UL << 4) - 1) << CQ_CONTEXT_CQC_BYTE_12_CQ_CQE_SHIFT_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_12_CEQN_S 24
|
||||
#define CQ_CONTEXT_CQC_BYTE_12_CEQN_M \
|
||||
(((1UL << 5) - 1) << CQ_CONTEXT_CQC_BYTE_12_CEQN_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_20_CUR_CQE_BA0_H_S 0
|
||||
#define CQ_CONTEXT_CQC_BYTE_20_CUR_CQE_BA0_H_M \
|
||||
(((1UL << 5) - 1) << CQ_CONTEXT_CQC_BYTE_20_CUR_CQE_BA0_H_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_20_CQ_CUR_INDEX_S 16
|
||||
#define CQ_CONTEXT_CQC_BYTE_20_CQ_CUR_INDEX_M \
|
||||
(((1UL << 16) - 1) << CQ_CONTEXT_CQC_BYTE_20_CQ_CUR_INDEX_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_20_CQE_TPTR_ADDR_H_S 8
|
||||
#define CQ_CONTEXT_CQC_BYTE_20_CQE_TPTR_ADDR_H_M \
|
||||
(((1UL << 5) - 1) << CQ_CONTEXT_CQC_BYTE_20_CQE_TPTR_ADDR_H_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_CUR_CQE_BA1_H_S 0
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_CUR_CQE_BA1_H_M \
|
||||
(((1UL << 5) - 1) << CQ_CONTEXT_CQC_BYTE_32_CUR_CQE_BA1_H_S)
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_SE_FLAG_S 9
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_CE_FLAG_S 8
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_NOTIFICATION_FLAG_S 14
|
||||
#define CQ_CQNTEXT_CQC_BYTE_32_TYPE_OF_COMPLETION_NOTIFICATION_S 15
|
||||
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_CQ_CONS_IDX_S 16
|
||||
#define CQ_CONTEXT_CQC_BYTE_32_CQ_CONS_IDX_M \
|
||||
(((1UL << 16) - 1) << CQ_CONTEXT_CQC_BYTE_32_CQ_CONS_IDX_S)
|
||||
|
||||
struct hns_roce_cqe {
|
||||
u32 cqe_byte_4;
|
||||
union {
|
||||
u32 r_key;
|
||||
u32 immediate_data;
|
||||
};
|
||||
u32 byte_cnt;
|
||||
u32 cqe_byte_16;
|
||||
u32 cqe_byte_20;
|
||||
u32 s_mac_l;
|
||||
u32 cqe_byte_28;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
#define CQE_BYTE_4_OWNER_S 7
|
||||
#define CQE_BYTE_4_SQ_RQ_FLAG_S 14
|
||||
|
||||
#define CQE_BYTE_4_STATUS_OF_THE_OPERATION_S 8
|
||||
#define CQE_BYTE_4_STATUS_OF_THE_OPERATION_M \
|
||||
(((1UL << 5) - 1) << CQE_BYTE_4_STATUS_OF_THE_OPERATION_S)
|
||||
|
||||
#define CQE_BYTE_4_WQE_INDEX_S 16
|
||||
#define CQE_BYTE_4_WQE_INDEX_M (((1UL << 14) - 1) << CQE_BYTE_4_WQE_INDEX_S)
|
||||
|
||||
#define CQE_BYTE_4_OPERATION_TYPE_S 0
|
||||
#define CQE_BYTE_4_OPERATION_TYPE_M \
|
||||
(((1UL << 4) - 1) << CQE_BYTE_4_OPERATION_TYPE_S)
|
||||
|
||||
#define CQE_BYTE_4_IMM_INDICATOR_S 15
|
||||
|
||||
#define CQE_BYTE_16_LOCAL_QPN_S 0
|
||||
#define CQE_BYTE_16_LOCAL_QPN_M (((1UL << 24) - 1) << CQE_BYTE_16_LOCAL_QPN_S)
|
||||
|
||||
#define CQE_BYTE_20_PORT_NUM_S 26
|
||||
#define CQE_BYTE_20_PORT_NUM_M (((1UL << 3) - 1) << CQE_BYTE_20_PORT_NUM_S)
|
||||
|
||||
#define CQE_BYTE_20_SL_S 24
|
||||
#define CQE_BYTE_20_SL_M (((1UL << 2) - 1) << CQE_BYTE_20_SL_S)
|
||||
|
||||
#define CQE_BYTE_20_REMOTE_QPN_S 0
|
||||
#define CQE_BYTE_20_REMOTE_QPN_M \
|
||||
(((1UL << 24) - 1) << CQE_BYTE_20_REMOTE_QPN_S)
|
||||
|
||||
#define CQE_BYTE_20_GRH_PRESENT_S 29
|
||||
|
||||
#define CQE_BYTE_28_P_KEY_IDX_S 16
|
||||
#define CQE_BYTE_28_P_KEY_IDX_M (((1UL << 16) - 1) << CQE_BYTE_28_P_KEY_IDX_S)
|
||||
|
||||
#define CQ_DB_REQ_NOT_SOL 0
|
||||
#define CQ_DB_REQ_NOT (1 << 16)
|
||||
|
||||
struct hns_roce_v1_mpt_entry {
|
||||
u32 mpt_byte_4;
|
||||
u32 pbl_addr_l;
|
||||
u32 mpt_byte_12;
|
||||
u32 virt_addr_l;
|
||||
u32 virt_addr_h;
|
||||
u32 length;
|
||||
u32 mpt_byte_28;
|
||||
u32 pa0_l;
|
||||
u32 mpt_byte_36;
|
||||
u32 mpt_byte_40;
|
||||
u32 mpt_byte_44;
|
||||
u32 mpt_byte_48;
|
||||
u32 pa4_l;
|
||||
u32 mpt_byte_56;
|
||||
u32 mpt_byte_60;
|
||||
u32 mpt_byte_64;
|
||||
};
|
||||
|
||||
#define MPT_BYTE_4_KEY_STATE_S 0
|
||||
#define MPT_BYTE_4_KEY_STATE_M (((1UL << 2) - 1) << MPT_BYTE_4_KEY_STATE_S)
|
||||
|
||||
#define MPT_BYTE_4_KEY_S 8
|
||||
#define MPT_BYTE_4_KEY_M (((1UL << 8) - 1) << MPT_BYTE_4_KEY_S)
|
||||
|
||||
#define MPT_BYTE_4_PAGE_SIZE_S 16
|
||||
#define MPT_BYTE_4_PAGE_SIZE_M (((1UL << 2) - 1) << MPT_BYTE_4_PAGE_SIZE_S)
|
||||
|
||||
#define MPT_BYTE_4_MW_TYPE_S 20
|
||||
|
||||
#define MPT_BYTE_4_MW_BIND_ENABLE_S 21
|
||||
|
||||
#define MPT_BYTE_4_OWN_S 22
|
||||
|
||||
#define MPT_BYTE_4_MEMORY_LOCATION_TYPE_S 24
|
||||
#define MPT_BYTE_4_MEMORY_LOCATION_TYPE_M \
|
||||
(((1UL << 2) - 1) << MPT_BYTE_4_MEMORY_LOCATION_TYPE_S)
|
||||
|
||||
#define MPT_BYTE_4_REMOTE_ATOMIC_S 26
|
||||
#define MPT_BYTE_4_LOCAL_WRITE_S 27
|
||||
#define MPT_BYTE_4_REMOTE_WRITE_S 28
|
||||
#define MPT_BYTE_4_REMOTE_READ_S 29
|
||||
#define MPT_BYTE_4_REMOTE_INVAL_ENABLE_S 30
|
||||
#define MPT_BYTE_4_ADDRESS_TYPE_S 31
|
||||
|
||||
#define MPT_BYTE_12_PBL_ADDR_H_S 0
|
||||
#define MPT_BYTE_12_PBL_ADDR_H_M \
|
||||
(((1UL << 17) - 1) << MPT_BYTE_12_PBL_ADDR_H_S)
|
||||
|
||||
#define MPT_BYTE_12_MW_BIND_COUNTER_S 17
|
||||
#define MPT_BYTE_12_MW_BIND_COUNTER_M \
|
||||
(((1UL << 15) - 1) << MPT_BYTE_12_MW_BIND_COUNTER_S)
|
||||
|
||||
#define MPT_BYTE_28_PD_S 0
|
||||
#define MPT_BYTE_28_PD_M (((1UL << 16) - 1) << MPT_BYTE_28_PD_S)
|
||||
|
||||
#define MPT_BYTE_28_L_KEY_IDX_L_S 16
|
||||
#define MPT_BYTE_28_L_KEY_IDX_L_M \
|
||||
(((1UL << 16) - 1) << MPT_BYTE_28_L_KEY_IDX_L_S)
|
||||
|
||||
#define MPT_BYTE_36_PA0_H_S 0
|
||||
#define MPT_BYTE_36_PA0_H_M (((1UL << 5) - 1) << MPT_BYTE_36_PA0_H_S)
|
||||
|
||||
#define MPT_BYTE_36_PA1_L_S 8
|
||||
#define MPT_BYTE_36_PA1_L_M (((1UL << 24) - 1) << MPT_BYTE_36_PA1_L_S)
|
||||
|
||||
#define MPT_BYTE_40_PA1_H_S 0
|
||||
#define MPT_BYTE_40_PA1_H_M (((1UL << 13) - 1) << MPT_BYTE_40_PA1_H_S)
|
||||
|
||||
#define MPT_BYTE_40_PA2_L_S 16
|
||||
#define MPT_BYTE_40_PA2_L_M (((1UL << 16) - 1) << MPT_BYTE_40_PA2_L_S)
|
||||
|
||||
#define MPT_BYTE_44_PA2_H_S 0
|
||||
#define MPT_BYTE_44_PA2_H_M (((1UL << 21) - 1) << MPT_BYTE_44_PA2_H_S)
|
||||
|
||||
#define MPT_BYTE_44_PA3_L_S 24
|
||||
#define MPT_BYTE_44_PA3_L_M (((1UL << 8) - 1) << MPT_BYTE_44_PA3_L_S)
|
||||
|
||||
#define MPT_BYTE_48_PA3_H_S 0
|
||||
#define MPT_BYTE_48_PA3_H_M (((1UL << 29) - 1) << MPT_BYTE_48_PA3_H_S)
|
||||
|
||||
#define MPT_BYTE_56_PA4_H_S 0
|
||||
#define MPT_BYTE_56_PA4_H_M (((1UL << 5) - 1) << MPT_BYTE_56_PA4_H_S)
|
||||
|
||||
#define MPT_BYTE_56_PA5_L_S 8
|
||||
#define MPT_BYTE_56_PA5_L_M (((1UL << 24) - 1) << MPT_BYTE_56_PA5_L_S)
|
||||
|
||||
#define MPT_BYTE_60_PA5_H_S 0
|
||||
#define MPT_BYTE_60_PA5_H_M (((1UL << 13) - 1) << MPT_BYTE_60_PA5_H_S)
|
||||
|
||||
#define MPT_BYTE_60_PA6_L_S 16
|
||||
#define MPT_BYTE_60_PA6_L_M (((1UL << 16) - 1) << MPT_BYTE_60_PA6_L_S)
|
||||
|
||||
#define MPT_BYTE_64_PA6_H_S 0
|
||||
#define MPT_BYTE_64_PA6_H_M (((1UL << 21) - 1) << MPT_BYTE_64_PA6_H_S)
|
||||
|
||||
#define MPT_BYTE_64_L_KEY_IDX_H_S 24
|
||||
#define MPT_BYTE_64_L_KEY_IDX_H_M \
|
||||
(((1UL << 8) - 1) << MPT_BYTE_64_L_KEY_IDX_H_S)
|
||||
|
||||
struct hns_roce_wqe_ctrl_seg {
|
||||
__be32 sgl_pa_h;
|
||||
__be32 flag;
|
||||
__be32 imm_data;
|
||||
__be32 msg_length;
|
||||
};
|
||||
|
||||
struct hns_roce_wqe_data_seg {
|
||||
__be64 addr;
|
||||
__be32 lkey;
|
||||
__be32 len;
|
||||
};
|
||||
|
||||
struct hns_roce_wqe_raddr_seg {
|
||||
__be32 rkey;
|
||||
__be32 len;/* reserved */
|
||||
__be64 raddr;
|
||||
};
|
||||
|
||||
struct hns_roce_rq_wqe_ctrl {
|
||||
|
||||
u32 rwqe_byte_4;
|
||||
u32 rocee_sgl_ba_l;
|
||||
u32 rwqe_byte_12;
|
||||
u32 reserved[5];
|
||||
};
|
||||
|
||||
#define RQ_WQE_CTRL_RWQE_BYTE_12_RWQE_SGE_NUM_S 16
|
||||
#define RQ_WQE_CTRL_RWQE_BYTE_12_RWQE_SGE_NUM_M \
|
||||
(((1UL << 6) - 1) << RQ_WQE_CTRL_RWQE_BYTE_12_RWQE_SGE_NUM_S)
|
||||
|
||||
#define HNS_ROCE_QP_DESTROY_TIMEOUT_MSECS 10000
|
||||
|
||||
#define GID_LEN 16
|
||||
|
||||
struct hns_roce_ud_send_wqe {
|
||||
u32 dmac_h;
|
||||
u32 u32_8;
|
||||
u32 immediate_data;
|
||||
|
||||
u32 u32_16;
|
||||
union {
|
||||
unsigned char dgid[GID_LEN];
|
||||
struct {
|
||||
u32 u32_20;
|
||||
u32 u32_24;
|
||||
u32 u32_28;
|
||||
u32 u32_32;
|
||||
};
|
||||
};
|
||||
|
||||
u32 u32_36;
|
||||
u32 u32_40;
|
||||
|
||||
u32 va0_l;
|
||||
u32 va0_h;
|
||||
u32 l_key0;
|
||||
|
||||
u32 va1_l;
|
||||
u32 va1_h;
|
||||
u32 l_key1;
|
||||
};
|
||||
|
||||
#define UD_SEND_WQE_U32_4_DMAC_0_S 0
|
||||
#define UD_SEND_WQE_U32_4_DMAC_0_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_4_DMAC_0_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_4_DMAC_1_S 8
|
||||
#define UD_SEND_WQE_U32_4_DMAC_1_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_4_DMAC_1_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_4_DMAC_2_S 16
|
||||
#define UD_SEND_WQE_U32_4_DMAC_2_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_4_DMAC_2_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_4_DMAC_3_S 24
|
||||
#define UD_SEND_WQE_U32_4_DMAC_3_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_4_DMAC_3_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_8_DMAC_4_S 0
|
||||
#define UD_SEND_WQE_U32_8_DMAC_4_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_8_DMAC_4_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_8_DMAC_5_S 8
|
||||
#define UD_SEND_WQE_U32_8_DMAC_5_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_8_DMAC_5_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_8_OPERATION_TYPE_S 16
|
||||
#define UD_SEND_WQE_U32_8_OPERATION_TYPE_M \
|
||||
(((1UL << 4) - 1) << UD_SEND_WQE_U32_8_OPERATION_TYPE_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_8_NUMBER_OF_DATA_SEG_S 24
|
||||
#define UD_SEND_WQE_U32_8_NUMBER_OF_DATA_SEG_M \
|
||||
(((1UL << 6) - 1) << UD_SEND_WQE_U32_8_NUMBER_OF_DATA_SEG_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_8_SEND_GL_ROUTING_HDR_FLAG_S 31
|
||||
|
||||
#define UD_SEND_WQE_U32_16_DEST_QP_S 0
|
||||
#define UD_SEND_WQE_U32_16_DEST_QP_M \
|
||||
(((1UL << 24) - 1) << UD_SEND_WQE_U32_16_DEST_QP_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_16_MAX_STATIC_RATE_S 24
|
||||
#define UD_SEND_WQE_U32_16_MAX_STATIC_RATE_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_16_MAX_STATIC_RATE_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_36_FLOW_LABEL_S 0
|
||||
#define UD_SEND_WQE_U32_36_FLOW_LABEL_M \
|
||||
(((1UL << 20) - 1) << UD_SEND_WQE_U32_36_FLOW_LABEL_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_36_PRIORITY_S 20
|
||||
#define UD_SEND_WQE_U32_36_PRIORITY_M \
|
||||
(((1UL << 4) - 1) << UD_SEND_WQE_U32_36_PRIORITY_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_36_SGID_INDEX_S 24
|
||||
#define UD_SEND_WQE_U32_36_SGID_INDEX_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_36_SGID_INDEX_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_40_HOP_LIMIT_S 0
|
||||
#define UD_SEND_WQE_U32_40_HOP_LIMIT_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_40_HOP_LIMIT_S)
|
||||
|
||||
#define UD_SEND_WQE_U32_40_TRAFFIC_CLASS_S 8
|
||||
#define UD_SEND_WQE_U32_40_TRAFFIC_CLASS_M \
|
||||
(((1UL << 8) - 1) << UD_SEND_WQE_U32_40_TRAFFIC_CLASS_S)
|
||||
|
||||
struct hns_roce_sqp_context {
|
||||
u32 qp1c_bytes_4;
|
||||
u32 sq_rq_bt_l;
|
||||
u32 qp1c_bytes_12;
|
||||
u32 qp1c_bytes_16;
|
||||
u32 qp1c_bytes_20;
|
||||
u32 qp1c_bytes_28;
|
||||
u32 cur_rq_wqe_ba_l;
|
||||
u32 qp1c_bytes_32;
|
||||
u32 cur_sq_wqe_ba_l;
|
||||
u32 qp1c_bytes_40;
|
||||
};
|
||||
|
||||
#define QP1C_BYTES_4_SQ_WQE_SHIFT_S 8
|
||||
#define QP1C_BYTES_4_SQ_WQE_SHIFT_M \
|
||||
(((1UL << 4) - 1) << QP1C_BYTES_4_SQ_WQE_SHIFT_S)
|
||||
|
||||
#define QP1C_BYTES_4_RQ_WQE_SHIFT_S 12
|
||||
#define QP1C_BYTES_4_RQ_WQE_SHIFT_M \
|
||||
(((1UL << 4) - 1) << QP1C_BYTES_4_RQ_WQE_SHIFT_S)
|
||||
|
||||
#define QP1C_BYTES_4_PD_S 16
|
||||
#define QP1C_BYTES_4_PD_M (((1UL << 16) - 1) << QP1C_BYTES_4_PD_S)
|
||||
|
||||
#define QP1C_BYTES_12_SQ_RQ_BT_H_S 0
|
||||
#define QP1C_BYTES_12_SQ_RQ_BT_H_M \
|
||||
(((1UL << 17) - 1) << QP1C_BYTES_12_SQ_RQ_BT_H_S)
|
||||
|
||||
#define QP1C_BYTES_16_RQ_HEAD_S 0
|
||||
#define QP1C_BYTES_16_RQ_HEAD_M (((1UL << 15) - 1) << QP1C_BYTES_16_RQ_HEAD_S)
|
||||
|
||||
#define QP1C_BYTES_16_PORT_NUM_S 16
|
||||
#define QP1C_BYTES_16_PORT_NUM_M \
|
||||
(((1UL << 3) - 1) << QP1C_BYTES_16_PORT_NUM_S)
|
||||
|
||||
#define QP1C_BYTES_16_SIGNALING_TYPE_S 27
|
||||
#define QP1C_BYTES_16_LOCAL_ENABLE_E2E_CREDIT_S 28
|
||||
#define QP1C_BYTES_16_RQ_BA_FLG_S 29
|
||||
#define QP1C_BYTES_16_SQ_BA_FLG_S 30
|
||||
#define QP1C_BYTES_16_QP1_ERR_S 31
|
||||
|
||||
#define QP1C_BYTES_20_SQ_HEAD_S 0
|
||||
#define QP1C_BYTES_20_SQ_HEAD_M (((1UL << 15) - 1) << QP1C_BYTES_20_SQ_HEAD_S)
|
||||
|
||||
#define QP1C_BYTES_20_PKEY_IDX_S 16
|
||||
#define QP1C_BYTES_20_PKEY_IDX_M \
|
||||
(((1UL << 16) - 1) << QP1C_BYTES_20_PKEY_IDX_S)
|
||||
|
||||
#define QP1C_BYTES_28_CUR_RQ_WQE_BA_H_S 0
|
||||
#define QP1C_BYTES_28_CUR_RQ_WQE_BA_H_M \
|
||||
(((1UL << 5) - 1) << QP1C_BYTES_28_CUR_RQ_WQE_BA_H_S)
|
||||
|
||||
#define QP1C_BYTES_28_RQ_CUR_IDX_S 16
|
||||
#define QP1C_BYTES_28_RQ_CUR_IDX_M \
|
||||
(((1UL << 15) - 1) << QP1C_BYTES_28_RQ_CUR_IDX_S)
|
||||
|
||||
#define QP1C_BYTES_32_TX_CQ_NUM_S 0
|
||||
#define QP1C_BYTES_32_TX_CQ_NUM_M \
|
||||
(((1UL << 16) - 1) << QP1C_BYTES_32_TX_CQ_NUM_S)
|
||||
|
||||
#define QP1C_BYTES_32_RX_CQ_NUM_S 16
|
||||
#define QP1C_BYTES_32_RX_CQ_NUM_M \
|
||||
(((1UL << 16) - 1) << QP1C_BYTES_32_RX_CQ_NUM_S)
|
||||
|
||||
#define QP1C_BYTES_40_CUR_SQ_WQE_BA_H_S 0
|
||||
#define QP1C_BYTES_40_CUR_SQ_WQE_BA_H_M \
|
||||
(((1UL << 5) - 1) << QP1C_BYTES_40_CUR_SQ_WQE_BA_H_S)
|
||||
|
||||
#define QP1C_BYTES_40_SQ_CUR_IDX_S 16
|
||||
#define QP1C_BYTES_40_SQ_CUR_IDX_M \
|
||||
(((1UL << 15) - 1) << QP1C_BYTES_40_SQ_CUR_IDX_S)
|
||||
|
||||
#define HNS_ROCE_WQE_INLINE (1UL<<31)
|
||||
#define HNS_ROCE_WQE_SE (1UL<<30)
|
||||
|
||||
#define HNS_ROCE_WQE_SGE_NUM_BIT 24
|
||||
#define HNS_ROCE_WQE_IMM (1UL<<23)
|
||||
#define HNS_ROCE_WQE_FENCE (1UL<<21)
|
||||
#define HNS_ROCE_WQE_CQ_NOTIFY (1UL<<20)
|
||||
|
||||
#define HNS_ROCE_WQE_OPCODE_SEND (0<<16)
|
||||
#define HNS_ROCE_WQE_OPCODE_RDMA_READ (1<<16)
|
||||
#define HNS_ROCE_WQE_OPCODE_RDMA_WRITE (2<<16)
|
||||
#define HNS_ROCE_WQE_OPCODE_LOCAL_INV (4<<16)
|
||||
#define HNS_ROCE_WQE_OPCODE_UD_SEND (7<<16)
|
||||
#define HNS_ROCE_WQE_OPCODE_MASK (15<<16)
|
||||
|
||||
struct hns_roce_qp_context {
|
||||
u32 qpc_bytes_4;
|
||||
u32 qpc_bytes_8;
|
||||
u32 qpc_bytes_12;
|
||||
u32 qpc_bytes_16;
|
||||
u32 sq_rq_bt_l;
|
||||
u32 qpc_bytes_24;
|
||||
u32 irrl_ba_l;
|
||||
u32 qpc_bytes_32;
|
||||
u32 qpc_bytes_36;
|
||||
u32 dmac_l;
|
||||
u32 qpc_bytes_44;
|
||||
u32 qpc_bytes_48;
|
||||
u8 dgid[16];
|
||||
u32 qpc_bytes_68;
|
||||
u32 cur_rq_wqe_ba_l;
|
||||
u32 qpc_bytes_76;
|
||||
u32 rx_rnr_time;
|
||||
u32 qpc_bytes_84;
|
||||
u32 qpc_bytes_88;
|
||||
union {
|
||||
u32 rx_sge_len;
|
||||
u32 dma_length;
|
||||
};
|
||||
union {
|
||||
u32 rx_sge_num;
|
||||
u32 rx_send_pktn;
|
||||
u32 r_key;
|
||||
};
|
||||
u32 va_l;
|
||||
u32 va_h;
|
||||
u32 qpc_bytes_108;
|
||||
u32 qpc_bytes_112;
|
||||
u32 rx_cur_sq_wqe_ba_l;
|
||||
u32 qpc_bytes_120;
|
||||
u32 qpc_bytes_124;
|
||||
u32 qpc_bytes_128;
|
||||
u32 qpc_bytes_132;
|
||||
u32 qpc_bytes_136;
|
||||
u32 qpc_bytes_140;
|
||||
u32 qpc_bytes_144;
|
||||
u32 qpc_bytes_148;
|
||||
union {
|
||||
u32 rnr_retry;
|
||||
u32 ack_time;
|
||||
};
|
||||
u32 qpc_bytes_156;
|
||||
u32 pkt_use_len;
|
||||
u32 qpc_bytes_164;
|
||||
u32 qpc_bytes_168;
|
||||
union {
|
||||
u32 sge_use_len;
|
||||
u32 pa_use_len;
|
||||
};
|
||||
u32 qpc_bytes_176;
|
||||
u32 qpc_bytes_180;
|
||||
u32 tx_cur_sq_wqe_ba_l;
|
||||
u32 qpc_bytes_188;
|
||||
u32 rvd21;
|
||||
};
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_4_TRANSPORT_SERVICE_TYPE_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_4_TRANSPORT_SERVICE_TYPE_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_4_TRANSPORT_SERVICE_TYPE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTE_4_ENABLE_FPMR_S 3
|
||||
#define QP_CONTEXT_QPC_BYTE_4_RDMA_READ_ENABLE_S 4
|
||||
#define QP_CONTEXT_QPC_BYTE_4_RDMA_WRITE_ENABLE_S 5
|
||||
#define QP_CONTEXT_QPC_BYTE_4_ATOMIC_OPERATION_ENABLE_S 6
|
||||
#define QP_CONTEXT_QPC_BYTE_4_RDMAR_USE_S 7
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_4_SQ_WQE_SHIFT_S 8
|
||||
#define QP_CONTEXT_QPC_BYTES_4_SQ_WQE_SHIFT_M \
|
||||
(((1UL << 4) - 1) << QP_CONTEXT_QPC_BYTES_4_SQ_WQE_SHIFT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_4_RQ_WQE_SHIFT_S 12
|
||||
#define QP_CONTEXT_QPC_BYTES_4_RQ_WQE_SHIFT_M \
|
||||
(((1UL << 4) - 1) << QP_CONTEXT_QPC_BYTES_4_RQ_WQE_SHIFT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_4_PD_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_4_PD_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_4_PD_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_8_TX_COMPLETION_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_8_TX_COMPLETION_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_8_TX_COMPLETION_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_8_RX_COMPLETION_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_8_RX_COMPLETION_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_8_RX_COMPLETION_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_12_SRQ_NUMBER_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_12_SRQ_NUMBER_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_12_SRQ_NUMBER_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_12_P_KEY_INDEX_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_12_P_KEY_INDEX_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_12_P_KEY_INDEX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_16_QP_NUM_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_16_QP_NUM_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_16_QP_NUM_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_24_SQ_RQ_BT_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_24_SQ_RQ_BT_H_M \
|
||||
(((1UL << 17) - 1) << QP_CONTEXT_QPC_BYTES_24_SQ_RQ_BT_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_24_MINIMUM_RNR_NAK_TIMER_S 18
|
||||
#define QP_CONTEXT_QPC_BYTES_24_MINIMUM_RNR_NAK_TIMER_M \
|
||||
(((1UL << 5) - 1) << QP_CONTEXT_QPC_BYTES_24_MINIMUM_RNR_NAK_TIMER_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTE_24_REMOTE_ENABLE_E2E_CREDITS_S 23
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_32_IRRL_BA_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_32_IRRL_BA_H_M \
|
||||
(((1UL << 17) - 1) << QP_CONTEXT_QPC_BYTES_32_IRRL_BA_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_32_MIG_STATE_S 18
|
||||
#define QP_CONTEXT_QPC_BYTES_32_MIG_STATE_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_32_MIG_STATE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTE_32_LOCAL_ENABLE_E2E_CREDITS_S 20
|
||||
#define QP_CONTEXT_QPC_BYTE_32_SIGNALING_TYPE_S 21
|
||||
#define QP_CONTEXT_QPC_BYTE_32_LOOPBACK_INDICATOR_S 22
|
||||
#define QP_CONTEXT_QPC_BYTE_32_GLOBAL_HEADER_S 23
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_32_RESPONDER_RESOURCES_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_32_RESPONDER_RESOURCES_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_32_RESPONDER_RESOURCES_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_36_DEST_QP_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_36_DEST_QP_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_36_DEST_QP_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_36_SGID_INDEX_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_36_SGID_INDEX_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_36_SGID_INDEX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_44_DMAC_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_44_DMAC_H_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_44_DMAC_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_44_MAXIMUM_STATIC_RATE_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_44_MAXIMUM_STATIC_RATE_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_44_MAXIMUM_STATIC_RATE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_44_HOPLMT_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_44_HOPLMT_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_44_HOPLMT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_48_FLOWLABEL_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_48_FLOWLABEL_M \
|
||||
(((1UL << 20) - 1) << QP_CONTEXT_QPC_BYTES_48_FLOWLABEL_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_48_TCLASS_S 20
|
||||
#define QP_CONTEXT_QPC_BYTES_48_TCLASS_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_48_TCLASS_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_48_MTU_S 28
|
||||
#define QP_CONTEXT_QPC_BYTES_48_MTU_M \
|
||||
(((1UL << 4) - 1) << QP_CONTEXT_QPC_BYTES_48_MTU_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_68_RQ_HEAD_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_68_RQ_HEAD_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_68_RQ_HEAD_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_68_RQ_CUR_INDEX_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_68_RQ_CUR_INDEX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_68_RQ_CUR_INDEX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_76_CUR_RQ_WQE_BA_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_76_CUR_RQ_WQE_BA_H_M \
|
||||
(((1UL << 5) - 1) << QP_CONTEXT_QPC_BYTES_76_CUR_RQ_WQE_BA_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_76_RX_REQ_MSN_S 8
|
||||
#define QP_CONTEXT_QPC_BYTES_76_RX_REQ_MSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_76_RX_REQ_MSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_84_LAST_ACK_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_84_LAST_ACK_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_84_LAST_ACK_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_84_TRRL_HEAD_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_84_TRRL_HEAD_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_84_TRRL_HEAD_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RX_REQ_EPSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RX_REQ_EPSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_88_RX_REQ_EPSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RX_REQ_PSN_ERR_FLAG_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RX_LAST_OPCODE_FLG_S 25
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RQ_REQ_LAST_OPERATION_TYPE_S 26
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RQ_REQ_LAST_OPERATION_TYPE_M \
|
||||
(((1UL << 2) - 1) << \
|
||||
QP_CONTEXT_QPC_BYTES_88_RQ_REQ_LAST_OPERATION_TYPE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RQ_REQ_RDMA_WR_FLAG_S 29
|
||||
#define QP_CONTEXT_QPC_BYTES_88_RQ_REQ_RDMA_WR_FLAG_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_88_RQ_REQ_RDMA_WR_FLAG_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_108_TRRL_SDB_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_108_TRRL_SDB_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_108_TRRL_SDB_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_108_TRRL_SDB_PSN_FLG_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_108_TRRL_TDB_PSN_FLG_S 25
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_112_TRRL_TDB_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_112_TRRL_TDB_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_112_TRRL_TDB_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_112_TRRL_TAIL_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_112_TRRL_TAIL_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_112_TRRL_TAIL_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_120_RX_CUR_SQ_WQE_BA_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_120_RX_CUR_SQ_WQE_BA_H_M \
|
||||
(((1UL << 5) - 1) << QP_CONTEXT_QPC_BYTES_120_RX_CUR_SQ_WQE_BA_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_124_RX_ACK_MSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_124_RX_ACK_MSN_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_124_RX_ACK_MSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_124_IRRL_MSG_IDX_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_124_IRRL_MSG_IDX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_124_IRRL_MSG_IDX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_128_RX_ACK_EPSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_128_RX_ACK_EPSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_128_RX_ACK_EPSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_128_RX_ACK_PSN_ERR_FLG_S 24
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_128_ACK_LAST_OPERATION_TYPE_S 25
|
||||
#define QP_CONTEXT_QPC_BYTES_128_ACK_LAST_OPERATION_TYPE_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_128_ACK_LAST_OPERATION_TYPE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_128_IRRL_PSN_VLD_FLG_S 27
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_132_IRRL_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_132_IRRL_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_132_IRRL_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_132_IRRL_TAIL_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_132_IRRL_TAIL_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_132_IRRL_TAIL_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_136_RETRY_MSG_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_136_RETRY_MSG_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_136_RETRY_MSG_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_136_RETRY_MSG_FPKT_PSN_L_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_136_RETRY_MSG_FPKT_PSN_L_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_136_RETRY_MSG_FPKT_PSN_L_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_140_RETRY_MSG_FPKT_PSN_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_140_RETRY_MSG_FPKT_PSN_H_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_140_RETRY_MSG_FPKT_PSN_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_140_RETRY_MSG_MSN_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_140_RETRY_MSG_MSN_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_140_RETRY_MSG_MSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_140_RNR_RETRY_FLG_S 31
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_144_QP_STATE_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_144_QP_STATE_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_144_QP_STATE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_148_CHECK_FLAG_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_148_CHECK_FLAG_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_148_CHECK_FLAG_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_148_RETRY_COUNT_S 2
|
||||
#define QP_CONTEXT_QPC_BYTES_148_RETRY_COUNT_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_148_RETRY_COUNT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_148_RNR_RETRY_COUNT_S 5
|
||||
#define QP_CONTEXT_QPC_BYTES_148_RNR_RETRY_COUNT_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_148_RNR_RETRY_COUNT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_148_LSN_S 8
|
||||
#define QP_CONTEXT_QPC_BYTES_148_LSN_M \
|
||||
(((1UL << 16) - 1) << QP_CONTEXT_QPC_BYTES_148_LSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_RETRY_COUNT_INIT_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_156_RETRY_COUNT_INIT_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_156_RETRY_COUNT_INIT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_ACK_TIMEOUT_S 3
|
||||
#define QP_CONTEXT_QPC_BYTES_156_ACK_TIMEOUT_M \
|
||||
(((1UL << 5) - 1) << QP_CONTEXT_QPC_BYTES_156_ACK_TIMEOUT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_RNR_RETRY_COUNT_INIT_S 8
|
||||
#define QP_CONTEXT_QPC_BYTES_156_RNR_RETRY_COUNT_INIT_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_156_RNR_RETRY_COUNT_INIT_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_PORT_NUM_S 11
|
||||
#define QP_CONTEXT_QPC_BYTES_156_PORT_NUM_M \
|
||||
(((1UL << 3) - 1) << QP_CONTEXT_QPC_BYTES_156_PORT_NUM_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_SL_S 14
|
||||
#define QP_CONTEXT_QPC_BYTES_156_SL_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_156_SL_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_INITIATOR_DEPTH_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_156_INITIATOR_DEPTH_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_156_INITIATOR_DEPTH_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_156_ACK_REQ_IND_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_156_ACK_REQ_IND_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_156_ACK_REQ_IND_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_164_SQ_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_164_SQ_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_164_SQ_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_164_IRRL_HEAD_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_164_IRRL_HEAD_M \
|
||||
(((1UL << 8) - 1) << QP_CONTEXT_QPC_BYTES_164_IRRL_HEAD_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_168_RETRY_SQ_PSN_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_168_RETRY_SQ_PSN_M \
|
||||
(((1UL << 24) - 1) << QP_CONTEXT_QPC_BYTES_168_RETRY_SQ_PSN_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_168_SGE_USE_FLA_S 24
|
||||
#define QP_CONTEXT_QPC_BYTES_168_SGE_USE_FLA_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_168_SGE_USE_FLA_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_168_DB_TYPE_S 26
|
||||
#define QP_CONTEXT_QPC_BYTES_168_DB_TYPE_M \
|
||||
(((1UL << 2) - 1) << QP_CONTEXT_QPC_BYTES_168_DB_TYPE_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_168_MSG_LP_IND_S 28
|
||||
#define QP_CONTEXT_QPC_BYTES_168_CSDB_LP_IND_S 29
|
||||
#define QP_CONTEXT_QPC_BYTES_168_QP_ERR_FLG_S 30
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_176_DB_CUR_INDEX_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_176_DB_CUR_INDEX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_176_DB_CUR_INDEX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_176_RETRY_DB_CUR_INDEX_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_176_RETRY_DB_CUR_INDEX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_176_RETRY_DB_CUR_INDEX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_180_SQ_HEAD_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_180_SQ_HEAD_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_180_SQ_HEAD_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_180_SQ_CUR_INDEX_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_180_SQ_CUR_INDEX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_180_SQ_CUR_INDEX_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_188_TX_CUR_SQ_WQE_BA_H_S 0
|
||||
#define QP_CONTEXT_QPC_BYTES_188_TX_CUR_SQ_WQE_BA_H_M \
|
||||
(((1UL << 5) - 1) << QP_CONTEXT_QPC_BYTES_188_TX_CUR_SQ_WQE_BA_H_S)
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_188_PKT_RETRY_FLG_S 8
|
||||
|
||||
#define QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_S 16
|
||||
#define QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_S)
|
||||
|
||||
struct hns_roce_rq_db {
|
||||
u32 u32_4;
|
||||
u32 u32_8;
|
||||
};
|
||||
|
||||
#define RQ_DOORBELL_U32_4_RQ_HEAD_S 0
|
||||
#define RQ_DOORBELL_U32_4_RQ_HEAD_M \
|
||||
(((1UL << 15) - 1) << RQ_DOORBELL_U32_4_RQ_HEAD_S)
|
||||
|
||||
#define RQ_DOORBELL_U32_8_QPN_S 0
|
||||
#define RQ_DOORBELL_U32_8_QPN_M (((1UL << 24) - 1) << RQ_DOORBELL_U32_8_QPN_S)
|
||||
|
||||
#define RQ_DOORBELL_U32_8_CMD_S 28
|
||||
#define RQ_DOORBELL_U32_8_CMD_M (((1UL << 3) - 1) << RQ_DOORBELL_U32_8_CMD_S)
|
||||
|
||||
#define RQ_DOORBELL_U32_8_HW_SYNC_S 31
|
||||
|
||||
struct hns_roce_sq_db {
|
||||
u32 u32_4;
|
||||
u32 u32_8;
|
||||
};
|
||||
|
||||
#define SQ_DOORBELL_U32_4_SQ_HEAD_S 0
|
||||
#define SQ_DOORBELL_U32_4_SQ_HEAD_M \
|
||||
(((1UL << 15) - 1) << SQ_DOORBELL_U32_4_SQ_HEAD_S)
|
||||
|
||||
#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_8_QPN_S 0
|
||||
#define SQ_DOORBELL_U32_8_QPN_M (((1UL << 24) - 1) << SQ_DOORBELL_U32_8_QPN_S)
|
||||
|
||||
#define SQ_DOORBELL_HW_SYNC_S 31
|
||||
|
||||
struct hns_roce_ext_db {
|
||||
int esdb_dep;
|
||||
int eodb_dep;
|
||||
struct hns_roce_buf_list *sdb_buf_list;
|
||||
struct hns_roce_buf_list *odb_buf_list;
|
||||
};
|
||||
|
||||
struct hns_roce_db_table {
|
||||
int sdb_ext_mod;
|
||||
int odb_ext_mod;
|
||||
struct hns_roce_ext_db *ext_db;
|
||||
};
|
||||
|
||||
struct hns_roce_v1_priv {
|
||||
struct hns_roce_db_table db_table;
|
||||
struct hns_roce_raq_table raq_table;
|
||||
};
|
||||
|
||||
int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool enable);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,614 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Hisilicon Limited.
|
||||
* Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* 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 <rdma/ib_umem.h>
|
||||
#include "hns_roce_device.h"
|
||||
#include "hns_roce_cmd.h"
|
||||
#include "hns_roce_hem.h"
|
||||
|
||||
static u32 hw_index_to_key(unsigned long ind)
|
||||
{
|
||||
return (u32)(ind >> 24) | (ind << 8);
|
||||
}
|
||||
|
||||
static unsigned long key_to_hw_index(u32 key)
|
||||
{
|
||||
return (key << 24) | (key >> 8);
|
||||
}
|
||||
|
||||
static int hns_roce_sw2hw_mpt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox,
|
||||
unsigned long mpt_index)
|
||||
{
|
||||
return hns_roce_cmd_mbox(hr_dev, mailbox->dma, 0, mpt_index, 0,
|
||||
HNS_ROCE_CMD_SW2HW_MPT,
|
||||
HNS_ROCE_CMD_TIME_CLASS_B);
|
||||
}
|
||||
|
||||
static int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox,
|
||||
unsigned long mpt_index)
|
||||
{
|
||||
return hns_roce_cmd_mbox(hr_dev, 0, mailbox ? mailbox->dma : 0,
|
||||
mpt_index, !mailbox, HNS_ROCE_CMD_HW2SW_MPT,
|
||||
HNS_ROCE_CMD_TIME_CLASS_B);
|
||||
}
|
||||
|
||||
static int hns_roce_buddy_alloc(struct hns_roce_buddy *buddy, int order,
|
||||
unsigned long *seg)
|
||||
{
|
||||
int o;
|
||||
u32 m;
|
||||
|
||||
spin_lock(&buddy->lock);
|
||||
|
||||
for (o = order; o <= buddy->max_order; ++o) {
|
||||
if (buddy->num_free[o]) {
|
||||
m = 1 << (buddy->max_order - o);
|
||||
*seg = find_first_bit(buddy->bits[o], m);
|
||||
if (*seg < m)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
spin_unlock(&buddy->lock);
|
||||
return -1;
|
||||
|
||||
found:
|
||||
clear_bit(*seg, buddy->bits[o]);
|
||||
--buddy->num_free[o];
|
||||
|
||||
while (o > order) {
|
||||
--o;
|
||||
*seg <<= 1;
|
||||
set_bit(*seg ^ 1, buddy->bits[o]);
|
||||
++buddy->num_free[o];
|
||||
}
|
||||
|
||||
spin_unlock(&buddy->lock);
|
||||
|
||||
*seg <<= order;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hns_roce_buddy_free(struct hns_roce_buddy *buddy, unsigned long seg,
|
||||
int order)
|
||||
{
|
||||
seg >>= order;
|
||||
|
||||
spin_lock(&buddy->lock);
|
||||
|
||||
while (test_bit(seg ^ 1, buddy->bits[order])) {
|
||||
clear_bit(seg ^ 1, buddy->bits[order]);
|
||||
--buddy->num_free[order];
|
||||
seg >>= 1;
|
||||
++order;
|
||||
}
|
||||
|
||||
set_bit(seg, buddy->bits[order]);
|
||||
++buddy->num_free[order];
|
||||
|
||||
spin_unlock(&buddy->lock);
|
||||
}
|
||||
|
||||
static int hns_roce_buddy_init(struct hns_roce_buddy *buddy, int max_order)
|
||||
{
|
||||
int i, s;
|
||||
|
||||
buddy->max_order = max_order;
|
||||
spin_lock_init(&buddy->lock);
|
||||
|
||||
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof(long *),
|
||||
GFP_KERNEL);
|
||||
buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof(int *),
|
||||
GFP_KERNEL);
|
||||
if (!buddy->bits || !buddy->num_free)
|
||||
goto err_out;
|
||||
|
||||
for (i = 0; i <= buddy->max_order; ++i) {
|
||||
s = BITS_TO_LONGS(1 << (buddy->max_order - i));
|
||||
buddy->bits[i] = kmalloc_array(s, sizeof(long), GFP_KERNEL);
|
||||
if (!buddy->bits[i])
|
||||
goto err_out_free;
|
||||
|
||||
bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i));
|
||||
}
|
||||
|
||||
set_bit(0, buddy->bits[buddy->max_order]);
|
||||
buddy->num_free[buddy->max_order] = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_free:
|
||||
for (i = 0; i <= buddy->max_order; ++i)
|
||||
kfree(buddy->bits[i]);
|
||||
|
||||
err_out:
|
||||
kfree(buddy->bits);
|
||||
kfree(buddy->num_free);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void hns_roce_buddy_cleanup(struct hns_roce_buddy *buddy)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= buddy->max_order; ++i)
|
||||
kfree(buddy->bits[i]);
|
||||
|
||||
kfree(buddy->bits);
|
||||
kfree(buddy->num_free);
|
||||
}
|
||||
|
||||
static int hns_roce_alloc_mtt_range(struct hns_roce_dev *hr_dev, int order,
|
||||
unsigned long *seg)
|
||||
{
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
int ret = 0;
|
||||
|
||||
ret = hns_roce_buddy_alloc(&mr_table->mtt_buddy, order, seg);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
if (hns_roce_table_get_range(hr_dev, &mr_table->mtt_table, *seg,
|
||||
*seg + (1 << order) - 1)) {
|
||||
hns_roce_buddy_free(&mr_table->mtt_buddy, *seg, order);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_mtt_init(struct hns_roce_dev *hr_dev, int npages, int page_shift,
|
||||
struct hns_roce_mtt *mtt)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
/* Page num is zero, correspond to DMA memory register */
|
||||
if (!npages) {
|
||||
mtt->order = -1;
|
||||
mtt->page_shift = HNS_ROCE_HEM_PAGE_SHIFT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Note: if page_shift is zero, FAST memory regsiter */
|
||||
mtt->page_shift = page_shift;
|
||||
|
||||
/* Compute MTT entry necessary */
|
||||
for (mtt->order = 0, i = HNS_ROCE_MTT_ENTRY_PER_SEG; i < npages;
|
||||
i <<= 1)
|
||||
++mtt->order;
|
||||
|
||||
/* Allocate MTT entry */
|
||||
ret = hns_roce_alloc_mtt_range(hr_dev, mtt->order, &mtt->first_seg);
|
||||
if (ret == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_mtt_cleanup(struct hns_roce_dev *hr_dev, struct hns_roce_mtt *mtt)
|
||||
{
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
|
||||
if (mtt->order < 0)
|
||||
return;
|
||||
|
||||
hns_roce_buddy_free(&mr_table->mtt_buddy, mtt->first_seg, mtt->order);
|
||||
hns_roce_table_put_range(hr_dev, &mr_table->mtt_table, mtt->first_seg,
|
||||
mtt->first_seg + (1 << mtt->order) - 1);
|
||||
}
|
||||
|
||||
static int hns_roce_mr_alloc(struct hns_roce_dev *hr_dev, u32 pd, u64 iova,
|
||||
u64 size, u32 access, int npages,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
unsigned long index = 0;
|
||||
int ret = 0;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
|
||||
/* Allocate a key for mr from mr_table */
|
||||
ret = hns_roce_bitmap_alloc(&hr_dev->mr_table.mtpt_bitmap, &index);
|
||||
if (ret == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
mr->iova = iova; /* MR va starting addr */
|
||||
mr->size = size; /* MR addr range */
|
||||
mr->pd = pd; /* MR num */
|
||||
mr->access = access; /* MR access permit */
|
||||
mr->enabled = 0; /* MR active status */
|
||||
mr->key = hw_index_to_key(index); /* MR key */
|
||||
|
||||
if (size == ~0ull) {
|
||||
mr->type = MR_TYPE_DMA;
|
||||
mr->pbl_buf = NULL;
|
||||
mr->pbl_dma_addr = 0;
|
||||
} else {
|
||||
mr->type = MR_TYPE_MR;
|
||||
mr->pbl_buf = dma_alloc_coherent(dev, npages * 8,
|
||||
&(mr->pbl_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_buf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hns_roce_mr_free(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
int npages = 0;
|
||||
int ret;
|
||||
|
||||
if (mr->enabled) {
|
||||
ret = hns_roce_hw2sw_mpt(hr_dev, NULL, key_to_hw_index(mr->key)
|
||||
& (hr_dev->caps.num_mtpts - 1));
|
||||
if (ret)
|
||||
dev_warn(dev, "HW2SW_MPT failed (%d)\n", ret);
|
||||
}
|
||||
|
||||
if (mr->size != ~0ULL) {
|
||||
npages = ib_umem_page_count(mr->umem);
|
||||
dma_free_coherent(dev, (unsigned int)(npages * 8), mr->pbl_buf,
|
||||
mr->pbl_dma_addr);
|
||||
}
|
||||
|
||||
hns_roce_bitmap_free(&hr_dev->mr_table.mtpt_bitmap,
|
||||
key_to_hw_index(mr->key));
|
||||
}
|
||||
|
||||
static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
int ret;
|
||||
unsigned long mtpt_idx = key_to_hw_index(mr->key);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_cmd_mailbox *mailbox;
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
|
||||
/* Prepare HEM entry memory */
|
||||
ret = hns_roce_table_get(hr_dev, &mr_table->mtpt_table, mtpt_idx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Allocate mailbox memory */
|
||||
mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
|
||||
if (IS_ERR(mailbox)) {
|
||||
ret = PTR_ERR(mailbox);
|
||||
goto err_table;
|
||||
}
|
||||
|
||||
ret = hr_dev->hw->write_mtpt(mailbox->buf, mr, mtpt_idx);
|
||||
if (ret) {
|
||||
dev_err(dev, "Write mtpt fail!\n");
|
||||
goto err_page;
|
||||
}
|
||||
|
||||
ret = hns_roce_sw2hw_mpt(hr_dev, mailbox,
|
||||
mtpt_idx & (hr_dev->caps.num_mtpts - 1));
|
||||
if (ret) {
|
||||
dev_err(dev, "SW2HW_MPT failed (%d)\n", ret);
|
||||
goto err_page;
|
||||
}
|
||||
|
||||
mr->enabled = 1;
|
||||
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
|
||||
|
||||
return 0;
|
||||
|
||||
err_page:
|
||||
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
|
||||
|
||||
err_table:
|
||||
hns_roce_table_put(hr_dev, &mr_table->mtpt_table, mtpt_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, u32 start_index,
|
||||
u32 npages, u64 *page_list)
|
||||
{
|
||||
u32 i = 0;
|
||||
__le64 *mtts = NULL;
|
||||
dma_addr_t dma_handle;
|
||||
u32 s = start_index * sizeof(u64);
|
||||
|
||||
/* All MTTs must fit in the same page */
|
||||
if (start_index / (PAGE_SIZE / sizeof(u64)) !=
|
||||
(start_index + npages - 1) / (PAGE_SIZE / sizeof(u64)))
|
||||
return -EINVAL;
|
||||
|
||||
if (start_index & (HNS_ROCE_MTT_ENTRY_PER_SEG - 1))
|
||||
return -EINVAL;
|
||||
|
||||
mtts = hns_roce_table_find(&hr_dev->mr_table.mtt_table,
|
||||
mtt->first_seg + s / hr_dev->caps.mtt_entry_sz,
|
||||
&dma_handle);
|
||||
if (!mtts)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Save page addr, low 12 bits : 0 */
|
||||
for (i = 0; i < npages; ++i)
|
||||
mtts[i] = (cpu_to_le64(page_list[i])) >> PAGE_ADDR_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, u32 start_index,
|
||||
u32 npages, u64 *page_list)
|
||||
{
|
||||
int chunk;
|
||||
int ret;
|
||||
|
||||
if (mtt->order < 0)
|
||||
return -EINVAL;
|
||||
|
||||
while (npages > 0) {
|
||||
chunk = min_t(int, PAGE_SIZE / sizeof(u64), npages);
|
||||
|
||||
ret = hns_roce_write_mtt_chunk(hr_dev, mtt, start_index, chunk,
|
||||
page_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
npages -= chunk;
|
||||
start_index += chunk;
|
||||
page_list += chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_buf_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, struct hns_roce_buf *buf)
|
||||
{
|
||||
u32 i = 0;
|
||||
int ret = 0;
|
||||
u64 *page_list = NULL;
|
||||
|
||||
page_list = kmalloc_array(buf->npages, sizeof(*page_list), GFP_KERNEL);
|
||||
if (!page_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < buf->npages; ++i) {
|
||||
if (buf->nbufs == 1)
|
||||
page_list[i] = buf->direct.map + (i << buf->page_shift);
|
||||
else
|
||||
page_list[i] = buf->page_list[i].map;
|
||||
|
||||
}
|
||||
ret = hns_roce_write_mtt(hr_dev, mtt, 0, buf->npages, page_list);
|
||||
|
||||
kfree(page_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_init_mr_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
int ret = 0;
|
||||
|
||||
ret = hns_roce_bitmap_init(&mr_table->mtpt_bitmap,
|
||||
hr_dev->caps.num_mtpts,
|
||||
hr_dev->caps.num_mtpts - 1,
|
||||
hr_dev->caps.reserved_mrws, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hns_roce_buddy_init(&mr_table->mtt_buddy,
|
||||
ilog2(hr_dev->caps.num_mtt_segs));
|
||||
if (ret)
|
||||
goto err_buddy;
|
||||
|
||||
return 0;
|
||||
|
||||
err_buddy:
|
||||
hns_roce_bitmap_cleanup(&mr_table->mtpt_bitmap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_mr_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
|
||||
hns_roce_buddy_cleanup(&mr_table->mtt_buddy);
|
||||
hns_roce_bitmap_cleanup(&mr_table->mtpt_bitmap);
|
||||
}
|
||||
|
||||
struct ib_mr *hns_roce_get_dma_mr(struct ib_pd *pd, int acc)
|
||||
{
|
||||
int ret = 0;
|
||||
struct hns_roce_mr *mr = NULL;
|
||||
|
||||
mr = kmalloc(sizeof(*mr), GFP_KERNEL);
|
||||
if (mr == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Allocate memory region key */
|
||||
ret = hns_roce_mr_alloc(to_hr_dev(pd->device), to_hr_pd(pd)->pdn, 0,
|
||||
~0ULL, acc, 0, mr);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
ret = hns_roce_mr_enable(to_hr_dev(pd->device), mr);
|
||||
if (ret)
|
||||
goto err_mr;
|
||||
|
||||
mr->ibmr.rkey = mr->ibmr.lkey = mr->key;
|
||||
mr->umem = NULL;
|
||||
|
||||
return &mr->ibmr;
|
||||
|
||||
err_mr:
|
||||
hns_roce_mr_free(to_hr_dev(pd->device), mr);
|
||||
|
||||
err_free:
|
||||
kfree(mr);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
int hns_roce_ib_umem_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, struct ib_umem *umem)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
int i, k, entry;
|
||||
int ret = 0;
|
||||
u64 *pages;
|
||||
u32 n;
|
||||
int len;
|
||||
|
||||
pages = (u64 *) __get_free_page(GFP_KERNEL);
|
||||
if (!pages)
|
||||
return -ENOMEM;
|
||||
|
||||
i = n = 0;
|
||||
|
||||
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
|
||||
len = sg_dma_len(sg) >> mtt->page_shift;
|
||||
for (k = 0; k < len; ++k) {
|
||||
pages[i++] = sg_dma_address(sg) + umem->page_size * k;
|
||||
if (i == PAGE_SIZE / sizeof(u64)) {
|
||||
ret = hns_roce_write_mtt(hr_dev, mtt, n, i,
|
||||
pages);
|
||||
if (ret)
|
||||
goto out;
|
||||
n += i;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
ret = hns_roce_write_mtt(hr_dev, mtt, n, i, pages);
|
||||
|
||||
out:
|
||||
free_page((unsigned long) pages);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_ib_umem_write_mr(struct hns_roce_mr *mr,
|
||||
struct ib_umem *umem)
|
||||
{
|
||||
int i = 0;
|
||||
int entry;
|
||||
struct scatterlist *sg;
|
||||
|
||||
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
|
||||
mr->pbl_buf[i] = ((u64)sg_dma_address(sg)) >> 12;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Memory barrier */
|
||||
mb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
u64 virt_addr, int access_flags,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_mr *mr = NULL;
|
||||
int ret = 0;
|
||||
int n = 0;
|
||||
|
||||
mr = kmalloc(sizeof(*mr), GFP_KERNEL);
|
||||
if (!mr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mr->umem = ib_umem_get(pd->uobject->context, start, length,
|
||||
access_flags, 0);
|
||||
if (IS_ERR(mr->umem)) {
|
||||
ret = PTR_ERR(mr->umem);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
n = ib_umem_page_count(mr->umem);
|
||||
if (mr->umem->page_size != HNS_ROCE_HEM_PAGE_SIZE) {
|
||||
dev_err(dev, "Just support 4K page size but is 0x%x now!\n",
|
||||
mr->umem->page_size);
|
||||
}
|
||||
|
||||
if (n > HNS_ROCE_MAX_MTPT_PBL_NUM) {
|
||||
dev_err(dev, " MR len %lld err. MR is limited to 4G at most!\n",
|
||||
length);
|
||||
goto err_umem;
|
||||
}
|
||||
|
||||
ret = hns_roce_mr_alloc(hr_dev, to_hr_pd(pd)->pdn, virt_addr, length,
|
||||
access_flags, n, mr);
|
||||
if (ret)
|
||||
goto err_umem;
|
||||
|
||||
ret = hns_roce_ib_umem_write_mr(mr, mr->umem);
|
||||
if (ret)
|
||||
goto err_mr;
|
||||
|
||||
ret = hns_roce_mr_enable(hr_dev, mr);
|
||||
if (ret)
|
||||
goto err_mr;
|
||||
|
||||
mr->ibmr.rkey = mr->ibmr.lkey = mr->key;
|
||||
|
||||
return &mr->ibmr;
|
||||
|
||||
err_mr:
|
||||
hns_roce_mr_free(hr_dev, mr);
|
||||
|
||||
err_umem:
|
||||
ib_umem_release(mr->umem);
|
||||
|
||||
err_free:
|
||||
kfree(mr);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
int hns_roce_dereg_mr(struct ib_mr *ibmr)
|
||||
{
|
||||
struct hns_roce_mr *mr = to_hr_mr(ibmr);
|
||||
|
||||
hns_roce_mr_free(to_hr_dev(ibmr->device), mr);
|
||||
if (mr->umem)
|
||||
ib_umem_release(mr->umem);
|
||||
|
||||
kfree(mr);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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 "hns_roce_device.h"
|
||||
|
||||
static int hns_roce_pd_alloc(struct hns_roce_dev *hr_dev, unsigned long *pdn)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
unsigned long pd_number;
|
||||
int ret = 0;
|
||||
|
||||
ret = hns_roce_bitmap_alloc(&hr_dev->pd_bitmap, &pd_number);
|
||||
if (ret == -1) {
|
||||
dev_err(dev, "alloc pdn from pdbitmap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*pdn = pd_number;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hns_roce_pd_free(struct hns_roce_dev *hr_dev, unsigned long pdn)
|
||||
{
|
||||
hns_roce_bitmap_free(&hr_dev->pd_bitmap, pdn);
|
||||
}
|
||||
|
||||
int hns_roce_init_pd_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
return hns_roce_bitmap_init(&hr_dev->pd_bitmap, hr_dev->caps.num_pds,
|
||||
hr_dev->caps.num_pds - 1,
|
||||
hr_dev->caps.reserved_pds, 0);
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_pd_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_bitmap_cleanup(&hr_dev->pd_bitmap);
|
||||
}
|
||||
|
||||
struct ib_pd *hns_roce_alloc_pd(struct ib_device *ib_dev,
|
||||
struct ib_ucontext *context,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_pd *pd;
|
||||
int ret;
|
||||
|
||||
pd = kmalloc(sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = hns_roce_pd_alloc(to_hr_dev(ib_dev), &pd->pdn);
|
||||
if (ret) {
|
||||
kfree(pd);
|
||||
dev_err(dev, "[alloc_pd]hns_roce_pd_alloc failed!\n");
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (context) {
|
||||
if (ib_copy_to_udata(udata, &pd->pdn, sizeof(u64))) {
|
||||
hns_roce_pd_free(to_hr_dev(ib_dev), pd->pdn);
|
||||
dev_err(dev, "[alloc_pd]ib_copy_to_udata failed!\n");
|
||||
kfree(pd);
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
return &pd->ibpd;
|
||||
}
|
||||
|
||||
int hns_roce_dealloc_pd(struct ib_pd *pd)
|
||||
{
|
||||
hns_roce_pd_free(to_hr_dev(pd->device), to_hr_pd(pd)->pdn);
|
||||
kfree(to_hr_pd(pd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_uar_alloc(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
|
||||
{
|
||||
struct resource *res;
|
||||
int ret = 0;
|
||||
|
||||
/* Using bitmap to manager UAR index */
|
||||
ret = hns_roce_bitmap_alloc(&hr_dev->uar_table.bitmap, &uar->index);
|
||||
if (ret == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
uar->index = (uar->index - 1) % hr_dev->caps.phy_num_uars + 1;
|
||||
|
||||
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
|
||||
uar->pfn = ((res->start) >> PAGE_SHIFT) + uar->index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_uar_free(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
|
||||
{
|
||||
hns_roce_bitmap_free(&hr_dev->uar_table.bitmap, uar->index);
|
||||
}
|
||||
|
||||
int hns_roce_init_uar_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
return hns_roce_bitmap_init(&hr_dev->uar_table.bitmap,
|
||||
hr_dev->caps.num_uars,
|
||||
hr_dev->caps.num_uars - 1,
|
||||
hr_dev->caps.reserved_uars, 0);
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_uar_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_bitmap_cleanup(&hr_dev->uar_table.bitmap);
|
||||
}
|
|
@ -0,0 +1,855 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Hisilicon Limited.
|
||||
* Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* 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 <rdma/ib_umem.h>
|
||||
#include "hns_roce_common.h"
|
||||
#include "hns_roce_device.h"
|
||||
#include "hns_roce_hem.h"
|
||||
#include "hns_roce_user.h"
|
||||
|
||||
#define DB_REG_OFFSET 0x1000
|
||||
#define SQP_NUM 12
|
||||
|
||||
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_qp *qp;
|
||||
|
||||
spin_lock(&qp_table->lock);
|
||||
|
||||
qp = __hns_roce_qp_lookup(hr_dev, qpn);
|
||||
if (qp)
|
||||
atomic_inc(&qp->refcount);
|
||||
|
||||
spin_unlock(&qp_table->lock);
|
||||
|
||||
if (!qp) {
|
||||
dev_warn(dev, "Async event for bogus QP %08x\n", qpn);
|
||||
return;
|
||||
}
|
||||
|
||||
qp->event(qp, (enum hns_roce_event)event_type);
|
||||
|
||||
if (atomic_dec_and_test(&qp->refcount))
|
||||
complete(&qp->free);
|
||||
}
|
||||
|
||||
static void hns_roce_ib_qp_event(struct hns_roce_qp *hr_qp,
|
||||
enum hns_roce_event type)
|
||||
{
|
||||
struct ib_event event;
|
||||
struct ib_qp *ibqp = &hr_qp->ibqp;
|
||||
|
||||
if (ibqp->event_handler) {
|
||||
event.device = ibqp->device;
|
||||
event.element.qp = ibqp;
|
||||
switch (type) {
|
||||
case HNS_ROCE_EVENT_TYPE_PATH_MIG:
|
||||
event.event = IB_EVENT_PATH_MIG;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_COMM_EST:
|
||||
event.event = IB_EVENT_COMM_EST;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_SQ_DRAINED:
|
||||
event.event = IB_EVENT_SQ_DRAINED;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH:
|
||||
event.event = IB_EVENT_QP_LAST_WQE_REACHED;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR:
|
||||
event.event = IB_EVENT_QP_FATAL;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED:
|
||||
event.event = IB_EVENT_PATH_MIG_ERR;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR:
|
||||
event.event = IB_EVENT_QP_REQ_ERR;
|
||||
break;
|
||||
case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
|
||||
event.event = IB_EVENT_QP_ACCESS_ERR;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(ibqp->device->dma_device, "roce_ib: Unexpected event type %d on QP %06lx\n",
|
||||
type, hr_qp->qpn);
|
||||
return;
|
||||
}
|
||||
ibqp->event_handler(&event, ibqp->qp_context);
|
||||
}
|
||||
}
|
||||
|
||||
static int hns_roce_reserve_range_qp(struct hns_roce_dev *hr_dev, int cnt,
|
||||
int align, unsigned long *base)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
int ret = 0;
|
||||
unsigned long qpn;
|
||||
|
||||
ret = hns_roce_bitmap_alloc_range(&qp_table->bitmap, cnt, align, &qpn);
|
||||
if (ret == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
*base = qpn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum hns_roce_qp_state to_hns_roce_state(enum ib_qp_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case IB_QPS_RESET:
|
||||
return HNS_ROCE_QP_STATE_RST;
|
||||
case IB_QPS_INIT:
|
||||
return HNS_ROCE_QP_STATE_INIT;
|
||||
case IB_QPS_RTR:
|
||||
return HNS_ROCE_QP_STATE_RTR;
|
||||
case IB_QPS_RTS:
|
||||
return HNS_ROCE_QP_STATE_RTS;
|
||||
case IB_QPS_SQD:
|
||||
return HNS_ROCE_QP_STATE_SQD;
|
||||
case IB_QPS_ERR:
|
||||
return HNS_ROCE_QP_STATE_ERR;
|
||||
default:
|
||||
return HNS_ROCE_QP_NUM_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
static int hns_roce_gsi_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
int ret;
|
||||
|
||||
if (!qpn)
|
||||
return -EINVAL;
|
||||
|
||||
hr_qp->qpn = qpn;
|
||||
|
||||
spin_lock_irq(&qp_table->lock);
|
||||
ret = radix_tree_insert(&hr_dev->qp_table_tree,
|
||||
hr_qp->qpn & (hr_dev->caps.num_qps - 1), hr_qp);
|
||||
spin_unlock_irq(&qp_table->lock);
|
||||
if (ret) {
|
||||
dev_err(&hr_dev->pdev->dev, "QPC radix_tree_insert failed\n");
|
||||
goto err_put_irrl;
|
||||
}
|
||||
|
||||
atomic_set(&hr_qp->refcount, 1);
|
||||
init_completion(&hr_qp->free);
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_irrl:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
int ret;
|
||||
|
||||
if (!qpn)
|
||||
return -EINVAL;
|
||||
|
||||
hr_qp->qpn = qpn;
|
||||
|
||||
/* Alloc memory for QPC */
|
||||
ret = hns_roce_table_get(hr_dev, &qp_table->qp_table, hr_qp->qpn);
|
||||
if (ret) {
|
||||
dev_err(dev, "QPC table get failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Alloc memory for IRRL */
|
||||
ret = hns_roce_table_get(hr_dev, &qp_table->irrl_table, hr_qp->qpn);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRRL table get failed\n");
|
||||
goto err_put_qp;
|
||||
}
|
||||
|
||||
spin_lock_irq(&qp_table->lock);
|
||||
ret = radix_tree_insert(&hr_dev->qp_table_tree,
|
||||
hr_qp->qpn & (hr_dev->caps.num_qps - 1), hr_qp);
|
||||
spin_unlock_irq(&qp_table->lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "QPC radix_tree_insert failed\n");
|
||||
goto err_put_irrl;
|
||||
}
|
||||
|
||||
atomic_set(&hr_qp->refcount, 1);
|
||||
init_completion(&hr_qp->free);
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_irrl:
|
||||
hns_roce_table_put(hr_dev, &qp_table->irrl_table, hr_qp->qpn);
|
||||
|
||||
err_put_qp:
|
||||
hns_roce_table_put(hr_dev, &qp_table->qp_table, hr_qp->qpn);
|
||||
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_qp_remove(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qp_table->lock, flags);
|
||||
radix_tree_delete(&hr_dev->qp_table_tree,
|
||||
hr_qp->qpn & (hr_dev->caps.num_qps - 1));
|
||||
spin_unlock_irqrestore(&qp_table->lock, flags);
|
||||
}
|
||||
|
||||
void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
|
||||
if (atomic_dec_and_test(&hr_qp->refcount))
|
||||
complete(&hr_qp->free);
|
||||
wait_for_completion(&hr_qp->free);
|
||||
|
||||
if ((hr_qp->ibqp.qp_type) != IB_QPT_GSI) {
|
||||
hns_roce_table_put(hr_dev, &qp_table->irrl_table, hr_qp->qpn);
|
||||
hns_roce_table_put(hr_dev, &qp_table->qp_table, hr_qp->qpn);
|
||||
}
|
||||
}
|
||||
|
||||
void hns_roce_release_range_qp(struct hns_roce_dev *hr_dev, int base_qpn,
|
||||
int cnt)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
|
||||
if (base_qpn < (hr_dev->caps.sqp_start + 2 * hr_dev->caps.num_ports))
|
||||
return;
|
||||
|
||||
hns_roce_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
|
||||
}
|
||||
|
||||
static int hns_roce_set_rq_size(struct hns_roce_dev *hr_dev,
|
||||
struct ib_qp_cap *cap, int is_user, int has_srq,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
u32 max_cnt;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
|
||||
/* Check the validity of QP support capacity */
|
||||
if (cap->max_recv_wr > hr_dev->caps.max_wqes ||
|
||||
cap->max_recv_sge > hr_dev->caps.max_rq_sg) {
|
||||
dev_err(dev, "RQ WR or sge error!max_recv_wr=%d max_recv_sge=%d\n",
|
||||
cap->max_recv_wr, cap->max_recv_sge);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If srq exit, set zero for relative number of rq */
|
||||
if (has_srq) {
|
||||
if (cap->max_recv_wr) {
|
||||
dev_dbg(dev, "srq no need config max_recv_wr\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hr_qp->rq.wqe_cnt = hr_qp->rq.max_gs = 0;
|
||||
} else {
|
||||
if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge)) {
|
||||
dev_err(dev, "user space no need config max_recv_wr max_recv_sge\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* In v1 engine, parameter verification procession */
|
||||
max_cnt = cap->max_recv_wr > HNS_ROCE_MIN_WQE_NUM ?
|
||||
cap->max_recv_wr : HNS_ROCE_MIN_WQE_NUM;
|
||||
hr_qp->rq.wqe_cnt = roundup_pow_of_two(max_cnt);
|
||||
|
||||
if ((u32)hr_qp->rq.wqe_cnt > hr_dev->caps.max_wqes) {
|
||||
dev_err(dev, "hns_roce_set_rq_size rq.wqe_cnt too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max_cnt = max(1U, cap->max_recv_sge);
|
||||
hr_qp->rq.max_gs = roundup_pow_of_two(max_cnt);
|
||||
/* WQE is fixed for 64B */
|
||||
hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz);
|
||||
}
|
||||
|
||||
cap->max_recv_wr = hr_qp->rq.max_post = hr_qp->rq.wqe_cnt;
|
||||
cap->max_recv_sge = hr_qp->rq.max_gs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_set_user_sq_size(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_qp *hr_qp,
|
||||
struct hns_roce_ib_create_qp *ucmd)
|
||||
{
|
||||
u32 roundup_sq_stride = roundup_pow_of_two(hr_dev->caps.max_sq_desc_sz);
|
||||
u8 max_sq_stride = ilog2(roundup_sq_stride);
|
||||
|
||||
/* Sanity check SQ size before proceeding */
|
||||
if ((u32)(1 << ucmd->log_sq_bb_count) > hr_dev->caps.max_wqes ||
|
||||
ucmd->log_sq_stride > max_sq_stride ||
|
||||
ucmd->log_sq_stride < HNS_ROCE_IB_MIN_SQ_STRIDE) {
|
||||
dev_err(&hr_dev->pdev->dev, "check SQ size error!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hr_qp->sq.wqe_cnt = 1 << ucmd->log_sq_bb_count;
|
||||
hr_qp->sq.wqe_shift = ucmd->log_sq_stride;
|
||||
|
||||
/* Get buf size, SQ and RQ are aligned to page_szie */
|
||||
hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
|
||||
hr_qp->rq.wqe_shift), PAGE_SIZE) +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
|
||||
hr_qp->sq.offset = 0;
|
||||
hr_qp->rq.offset = HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev,
|
||||
struct ib_qp_cap *cap,
|
||||
enum ib_qp_type type,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u32 max_cnt;
|
||||
(void)type;
|
||||
|
||||
if (cap->max_send_wr > hr_dev->caps.max_wqes ||
|
||||
cap->max_send_sge > hr_dev->caps.max_sq_sg ||
|
||||
cap->max_inline_data > hr_dev->caps.max_sq_inline) {
|
||||
dev_err(dev, "hns_roce_set_kernel_sq_size error1\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hr_qp->sq.wqe_shift = ilog2(hr_dev->caps.max_sq_desc_sz);
|
||||
hr_qp->sq_max_wqes_per_wr = 1;
|
||||
hr_qp->sq_spare_wqes = 0;
|
||||
|
||||
/* In v1 engine, parameter verification procession */
|
||||
max_cnt = cap->max_send_wr > HNS_ROCE_MIN_WQE_NUM ?
|
||||
cap->max_send_wr : HNS_ROCE_MIN_WQE_NUM;
|
||||
hr_qp->sq.wqe_cnt = roundup_pow_of_two(max_cnt);
|
||||
if ((u32)hr_qp->sq.wqe_cnt > hr_dev->caps.max_wqes) {
|
||||
dev_err(dev, "hns_roce_set_kernel_sq_size sq.wqe_cnt too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get data_seg numbers */
|
||||
max_cnt = max(1U, cap->max_send_sge);
|
||||
hr_qp->sq.max_gs = roundup_pow_of_two(max_cnt);
|
||||
|
||||
/* Get buf size, SQ and RQ are aligned to page_szie */
|
||||
hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
|
||||
hr_qp->rq.wqe_shift), PAGE_SIZE) +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
hr_qp->sq.offset = 0;
|
||||
hr_qp->rq.offset = HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
|
||||
/* Get wr and sge number which send */
|
||||
cap->max_send_wr = hr_qp->sq.max_post = hr_qp->sq.wqe_cnt;
|
||||
cap->max_send_sge = hr_qp->sq.max_gs;
|
||||
|
||||
/* We don't support inline sends for kernel QPs (yet) */
|
||||
cap->max_inline_data = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
struct ib_pd *ib_pd,
|
||||
struct ib_qp_init_attr *init_attr,
|
||||
struct ib_udata *udata, unsigned long sqpn,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_ib_create_qp ucmd;
|
||||
unsigned long qpn = 0;
|
||||
int ret = 0;
|
||||
|
||||
mutex_init(&hr_qp->mutex);
|
||||
spin_lock_init(&hr_qp->sq.lock);
|
||||
spin_lock_init(&hr_qp->rq.lock);
|
||||
|
||||
hr_qp->state = IB_QPS_RESET;
|
||||
|
||||
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
|
||||
hr_qp->sq_signal_bits = IB_SIGNAL_ALL_WR;
|
||||
else
|
||||
hr_qp->sq_signal_bits = IB_SIGNAL_REQ_WR;
|
||||
|
||||
ret = hns_roce_set_rq_size(hr_dev, &init_attr->cap, !!ib_pd->uobject,
|
||||
!!init_attr->srq, hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_set_rq_size failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (ib_pd->uobject) {
|
||||
if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
|
||||
dev_err(dev, "ib_copy_from_udata error for create qp\n");
|
||||
ret = -EFAULT;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ret = hns_roce_set_user_sq_size(hr_dev, hr_qp, &ucmd);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_set_user_sq_size error for create qp\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
hr_qp->umem = ib_umem_get(ib_pd->uobject->context,
|
||||
ucmd.buf_addr, hr_qp->buff_size, 0,
|
||||
0);
|
||||
if (IS_ERR(hr_qp->umem)) {
|
||||
dev_err(dev, "ib_umem_get error for create qp\n");
|
||||
ret = PTR_ERR(hr_qp->umem);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ret = hns_roce_mtt_init(hr_dev, ib_umem_page_count(hr_qp->umem),
|
||||
ilog2((unsigned int)hr_qp->umem->page_size),
|
||||
&hr_qp->mtt);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_mtt_init error for create qp\n");
|
||||
goto err_buf;
|
||||
}
|
||||
|
||||
ret = hns_roce_ib_umem_write_mtt(hr_dev, &hr_qp->mtt,
|
||||
hr_qp->umem);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_ib_umem_write_mtt error for create qp\n");
|
||||
goto err_mtt;
|
||||
}
|
||||
} else {
|
||||
if (init_attr->create_flags &
|
||||
IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
|
||||
dev_err(dev, "init_attr->create_flags error!\n");
|
||||
ret = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) {
|
||||
dev_err(dev, "init_attr->create_flags error!\n");
|
||||
ret = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Set SQ size */
|
||||
ret = hns_roce_set_kernel_sq_size(hr_dev, &init_attr->cap,
|
||||
init_attr->qp_type, hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_set_kernel_sq_size error!\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* QP doorbell register address */
|
||||
hr_qp->sq.db_reg_l = hr_dev->reg_base + ROCEE_DB_SQ_L_0_REG +
|
||||
DB_REG_OFFSET * hr_dev->priv_uar.index;
|
||||
hr_qp->rq.db_reg_l = hr_dev->reg_base +
|
||||
ROCEE_DB_OTHERS_L_0_REG +
|
||||
DB_REG_OFFSET * hr_dev->priv_uar.index;
|
||||
|
||||
/* Allocate QP buf */
|
||||
if (hns_roce_buf_alloc(hr_dev, hr_qp->buff_size, PAGE_SIZE * 2,
|
||||
&hr_qp->hr_buf)) {
|
||||
dev_err(dev, "hns_roce_buf_alloc error!\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Write MTT */
|
||||
ret = hns_roce_mtt_init(hr_dev, hr_qp->hr_buf.npages,
|
||||
hr_qp->hr_buf.page_shift, &hr_qp->mtt);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_mtt_init error for kernel create qp\n");
|
||||
goto err_buf;
|
||||
}
|
||||
|
||||
ret = hns_roce_buf_write_mtt(hr_dev, &hr_qp->mtt,
|
||||
&hr_qp->hr_buf);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_buf_write_mtt error for kernel create qp\n");
|
||||
goto err_mtt;
|
||||
}
|
||||
|
||||
hr_qp->sq.wrid = kmalloc_array(hr_qp->sq.wqe_cnt, sizeof(u64),
|
||||
GFP_KERNEL);
|
||||
hr_qp->rq.wrid = kmalloc_array(hr_qp->rq.wqe_cnt, sizeof(u64),
|
||||
GFP_KERNEL);
|
||||
if (!hr_qp->sq.wrid || !hr_qp->rq.wrid) {
|
||||
ret = -ENOMEM;
|
||||
goto err_wrid;
|
||||
}
|
||||
}
|
||||
|
||||
if (sqpn) {
|
||||
qpn = sqpn;
|
||||
} else {
|
||||
/* Get QPN */
|
||||
ret = hns_roce_reserve_range_qp(hr_dev, 1, 1, &qpn);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_reserve_range_qp alloc qpn error\n");
|
||||
goto err_wrid;
|
||||
}
|
||||
}
|
||||
|
||||
if ((init_attr->qp_type) == IB_QPT_GSI) {
|
||||
ret = hns_roce_gsi_qp_alloc(hr_dev, qpn, hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_qp_alloc failed!\n");
|
||||
goto err_qpn;
|
||||
}
|
||||
} else {
|
||||
ret = hns_roce_qp_alloc(hr_dev, qpn, hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_qp_alloc failed!\n");
|
||||
goto err_qpn;
|
||||
}
|
||||
}
|
||||
|
||||
if (sqpn)
|
||||
hr_qp->doorbell_qpn = 1;
|
||||
else
|
||||
hr_qp->doorbell_qpn = cpu_to_le64(hr_qp->qpn);
|
||||
|
||||
hr_qp->event = hns_roce_ib_qp_event;
|
||||
|
||||
return 0;
|
||||
|
||||
err_qpn:
|
||||
if (!sqpn)
|
||||
hns_roce_release_range_qp(hr_dev, qpn, 1);
|
||||
|
||||
err_wrid:
|
||||
kfree(hr_qp->sq.wrid);
|
||||
kfree(hr_qp->rq.wrid);
|
||||
|
||||
err_mtt:
|
||||
hns_roce_mtt_cleanup(hr_dev, &hr_qp->mtt);
|
||||
|
||||
err_buf:
|
||||
if (ib_pd->uobject)
|
||||
ib_umem_release(hr_qp->umem);
|
||||
else
|
||||
hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
|
||||
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
|
||||
struct ib_qp_init_attr *init_attr,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_sqp *hr_sqp;
|
||||
struct hns_roce_qp *hr_qp;
|
||||
int ret;
|
||||
|
||||
switch (init_attr->qp_type) {
|
||||
case IB_QPT_RC: {
|
||||
hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
|
||||
if (!hr_qp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata, 0,
|
||||
hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "Create RC QP failed\n");
|
||||
kfree(hr_qp);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
hr_qp->ibqp.qp_num = hr_qp->qpn;
|
||||
|
||||
break;
|
||||
}
|
||||
case IB_QPT_GSI: {
|
||||
/* Userspace is not allowed to create special QPs: */
|
||||
if (pd->uobject) {
|
||||
dev_err(dev, "not support usr space GSI\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
hr_sqp = kzalloc(sizeof(*hr_sqp), GFP_KERNEL);
|
||||
if (!hr_sqp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hr_qp = &hr_sqp->hr_qp;
|
||||
|
||||
ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata,
|
||||
hr_dev->caps.sqp_start +
|
||||
hr_dev->caps.num_ports +
|
||||
init_attr->port_num - 1, hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "Create GSI QP failed!\n");
|
||||
kfree(hr_sqp);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
hr_qp->port = (init_attr->port_num - 1);
|
||||
hr_qp->ibqp.qp_num = hr_dev->caps.sqp_start +
|
||||
hr_dev->caps.num_ports +
|
||||
init_attr->port_num - 1;
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
dev_err(dev, "not support QP type %d\n", init_attr->qp_type);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return &hr_qp->ibqp;
|
||||
}
|
||||
|
||||
int to_hr_qp_type(int qp_type)
|
||||
{
|
||||
int transport_type;
|
||||
|
||||
if (qp_type == IB_QPT_RC)
|
||||
transport_type = SERV_TYPE_RC;
|
||||
else if (qp_type == IB_QPT_UC)
|
||||
transport_type = SERV_TYPE_UC;
|
||||
else if (qp_type == IB_QPT_UD)
|
||||
transport_type = SERV_TYPE_UD;
|
||||
else if (qp_type == IB_QPT_GSI)
|
||||
transport_type = SERV_TYPE_UD;
|
||||
else
|
||||
transport_type = -1;
|
||||
|
||||
return transport_type;
|
||||
}
|
||||
|
||||
int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
int attr_mask, struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
||||
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
|
||||
enum ib_qp_state cur_state, new_state;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
int ret = -EINVAL;
|
||||
int p;
|
||||
|
||||
mutex_lock(&hr_qp->mutex);
|
||||
|
||||
cur_state = attr_mask & IB_QP_CUR_STATE ?
|
||||
attr->cur_qp_state : (enum ib_qp_state)hr_qp->state;
|
||||
new_state = attr_mask & IB_QP_STATE ?
|
||||
attr->qp_state : cur_state;
|
||||
|
||||
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask,
|
||||
IB_LINK_LAYER_ETHERNET)) {
|
||||
dev_err(dev, "ib_modify_qp_is_ok failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((attr_mask & IB_QP_PORT) &&
|
||||
(attr->port_num == 0 || attr->port_num > hr_dev->caps.num_ports)) {
|
||||
dev_err(dev, "attr port_num invalid.attr->port_num=%d\n",
|
||||
attr->port_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attr_mask & IB_QP_PKEY_INDEX) {
|
||||
p = attr_mask & IB_QP_PORT ? (attr->port_num - 1) : hr_qp->port;
|
||||
if (attr->pkey_index >= hr_dev->caps.pkey_table_len[p]) {
|
||||
dev_err(dev, "attr pkey_index invalid.attr->pkey_index=%d\n",
|
||||
attr->pkey_index);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
|
||||
attr->max_rd_atomic > hr_dev->caps.max_qp_init_rdma) {
|
||||
dev_err(dev, "attr max_rd_atomic invalid.attr->max_rd_atomic=%d\n",
|
||||
attr->max_rd_atomic);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
|
||||
attr->max_dest_rd_atomic > hr_dev->caps.max_qp_dest_rdma) {
|
||||
dev_err(dev, "attr max_dest_rd_atomic invalid.attr->max_dest_rd_atomic=%d\n",
|
||||
attr->max_dest_rd_atomic);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cur_state == new_state && cur_state == IB_QPS_RESET) {
|
||||
ret = -EPERM;
|
||||
dev_err(dev, "cur_state=%d new_state=%d\n", cur_state,
|
||||
new_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hr_dev->hw->modify_qp(ibqp, attr, attr_mask, cur_state,
|
||||
new_state);
|
||||
|
||||
out:
|
||||
mutex_unlock(&hr_qp->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_lock_cqs(struct hns_roce_cq *send_cq, struct hns_roce_cq *recv_cq)
|
||||
__acquires(&send_cq->lock) __acquires(&recv_cq->lock)
|
||||
{
|
||||
if (send_cq == recv_cq) {
|
||||
spin_lock_irq(&send_cq->lock);
|
||||
__acquire(&recv_cq->lock);
|
||||
} else if (send_cq->cqn < recv_cq->cqn) {
|
||||
spin_lock_irq(&send_cq->lock);
|
||||
spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
|
||||
} else {
|
||||
spin_lock_irq(&recv_cq->lock);
|
||||
spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
}
|
||||
|
||||
void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq,
|
||||
struct hns_roce_cq *recv_cq) __releases(&send_cq->lock)
|
||||
__releases(&recv_cq->lock)
|
||||
{
|
||||
if (send_cq == recv_cq) {
|
||||
__release(&recv_cq->lock);
|
||||
spin_unlock_irq(&send_cq->lock);
|
||||
} else if (send_cq->cqn < recv_cq->cqn) {
|
||||
spin_unlock(&recv_cq->lock);
|
||||
spin_unlock_irq(&send_cq->lock);
|
||||
} else {
|
||||
spin_unlock(&send_cq->lock);
|
||||
spin_unlock_irq(&recv_cq->lock);
|
||||
}
|
||||
}
|
||||
|
||||
__be32 send_ieth(struct ib_send_wr *wr)
|
||||
{
|
||||
switch (wr->opcode) {
|
||||
case IB_WR_SEND_WITH_IMM:
|
||||
case IB_WR_RDMA_WRITE_WITH_IMM:
|
||||
return cpu_to_le32(wr->ex.imm_data);
|
||||
case IB_WR_SEND_WITH_INV:
|
||||
return cpu_to_le32(wr->ex.invalidate_rkey);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void *get_wqe(struct hns_roce_qp *hr_qp, int offset)
|
||||
{
|
||||
|
||||
return hns_roce_buf_offset(&hr_qp->hr_buf, offset);
|
||||
}
|
||||
|
||||
void *get_recv_wqe(struct hns_roce_qp *hr_qp, int n)
|
||||
{
|
||||
struct ib_qp *ibqp = &hr_qp->ibqp;
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
||||
|
||||
if ((n < 0) || (n > hr_qp->rq.wqe_cnt)) {
|
||||
dev_err(&hr_dev->pdev->dev, "rq wqe index:%d,rq wqe cnt:%d\r\n",
|
||||
n, hr_qp->rq.wqe_cnt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_wqe(hr_qp, hr_qp->rq.offset + (n << hr_qp->rq.wqe_shift));
|
||||
}
|
||||
|
||||
void *get_send_wqe(struct hns_roce_qp *hr_qp, int n)
|
||||
{
|
||||
struct ib_qp *ibqp = &hr_qp->ibqp;
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
||||
|
||||
if ((n < 0) || (n > hr_qp->sq.wqe_cnt)) {
|
||||
dev_err(&hr_dev->pdev->dev, "sq wqe index:%d,sq wqe cnt:%d\r\n",
|
||||
n, hr_qp->sq.wqe_cnt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_wqe(hr_qp, hr_qp->sq.offset + (n << hr_qp->sq.wqe_shift));
|
||||
}
|
||||
|
||||
bool hns_roce_wq_overflow(struct hns_roce_wq *hr_wq, int nreq,
|
||||
struct ib_cq *ib_cq)
|
||||
{
|
||||
struct hns_roce_cq *hr_cq;
|
||||
u32 cur;
|
||||
|
||||
cur = hr_wq->head - hr_wq->tail;
|
||||
if (likely(cur + nreq < hr_wq->max_post))
|
||||
return 0;
|
||||
|
||||
hr_cq = to_hr_cq(ib_cq);
|
||||
spin_lock(&hr_cq->lock);
|
||||
cur = hr_wq->head - hr_wq->tail;
|
||||
spin_unlock(&hr_cq->lock);
|
||||
|
||||
return cur + nreq >= hr_wq->max_post;
|
||||
}
|
||||
|
||||
int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
int reserved_from_top = 0;
|
||||
int ret;
|
||||
|
||||
spin_lock_init(&qp_table->lock);
|
||||
INIT_RADIX_TREE(&hr_dev->qp_table_tree, GFP_ATOMIC);
|
||||
|
||||
/* A port include two SQP, six port total 12 */
|
||||
ret = hns_roce_bitmap_init(&qp_table->bitmap, hr_dev->caps.num_qps,
|
||||
hr_dev->caps.num_qps - 1,
|
||||
hr_dev->caps.sqp_start + SQP_NUM,
|
||||
reserved_from_top);
|
||||
if (ret) {
|
||||
dev_err(&hr_dev->pdev->dev, "qp bitmap init failed!error=%d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_bitmap_cleanup(&hr_dev->qp_table.bitmap);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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_USER_H
|
||||
#define _HNS_ROCE_USER_H
|
||||
|
||||
struct hns_roce_ib_create_cq {
|
||||
__u64 buf_addr;
|
||||
};
|
||||
|
||||
struct hns_roce_ib_create_qp {
|
||||
__u64 buf_addr;
|
||||
__u64 db_addr;
|
||||
__u8 log_sq_bb_count;
|
||||
__u8 log_sq_stride;
|
||||
__u8 sq_no_prefetch;
|
||||
__u8 reserved[5];
|
||||
};
|
||||
|
||||
struct hns_roce_ib_alloc_ucontext_resp {
|
||||
__u32 qp_tab_size;
|
||||
};
|
||||
|
||||
#endif /*_HNS_ROCE_USER_H */
|
Loading…
Reference in New Issue