// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022, Microsoft Corporation. All rights reserved.
*/
#include "mana_ib.h"
#include "linux/pci.h"
void mana_ib_uncfg_vport(struct mana_ib_dev *dev, struct mana_ib_pd *pd,
u32 port)
{
struct mana_port_context *mpc;
struct net_device *ndev;
ndev = mana_ib_get_netdev(&dev->ib_dev, port);
mpc = netdev_priv(ndev);
mutex_lock(&pd->vport_mutex);
pd->vport_use_count--;
WARN_ON(pd->vport_use_count < 0);
if (!pd->vport_use_count)
mana_uncfg_vport(mpc);
mutex_unlock(&pd->vport_mutex);
}
int mana_ib_cfg_vport(struct mana_ib_dev *dev, u32 port, struct mana_ib_pd *pd,
u32 doorbell_id)
{
struct mana_port_context *mpc;
struct net_device *ndev;
int err;
ndev = mana_ib_get_netdev(&dev->ib_dev, port);
mpc = netdev_priv(ndev);
mutex_lock(&pd->vport_mutex);
pd->vport_use_count++;
if (pd->vport_use_count > 1) {
ibdev_dbg(&dev->ib_dev,
"Skip as this PD is already configured vport\n");
mutex_unlock(&pd->vport_mutex);
return 0;
}
err = mana_cfg_vport(mpc, pd->pdn, doorbell_id);
if (err) {
pd->vport_use_count--;
mutex_unlock(&pd->vport_mutex);
ibdev_dbg(&dev->ib_dev, "Failed to configure vPort %d\n", err);
return err;
}
mutex_unlock(&pd->vport_mutex);
pd->tx_shortform_allowed = mpc->tx_shortform_allowed;
pd->tx_vp_offset = mpc->tx_vp_offset;
ibdev_dbg(&dev->ib_dev, "vport handle %llx pdid %x doorbell_id %x\n",
mpc->port_handle, pd->pdn, doorbell_id);
return 0;
}
int mana_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
{
struct mana_ib_pd *pd = container_of(ibpd, struct mana_ib_pd, ibpd);
struct ib_device *ibdev = ibpd->device;
struct gdma_create_pd_resp resp = {};
struct gdma_create_pd_req req = {};
enum gdma_pd_flags flags = 0;
struct mana_ib_dev *dev;
struct gdma_context *gc;
int err;
dev = container_of(ibdev, struct mana_ib_dev, ib_dev);
gc = mdev_to_gc(dev);
mana_gd_init_req_hdr(&req.hdr, GDMA_CREATE_PD, sizeof(req),
sizeof(resp));
if (!udata)
flags |= GDMA_PD_FLAG_ALLOW_GPA_MR;
req.flags = flags;
err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);
if (err)
return err;
pd->pd_handle = resp.pd_handle;
pd->pdn = resp.pd_id;
ibdev_dbg(&dev->ib_dev, "pd_handle 0x%llx pd_id %d\n",
pd->pd_handle, pd->pdn);
mutex_init(&pd->vport_mutex);
pd->vport_use_count = 0;
return 0;
}
int mana_ib_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
{
struct mana_ib_pd *pd = container_of(ibpd, struct mana_ib_pd, ibpd);
struct ib_device *ibdev = ibpd->device;
struct gdma_destory_pd_resp resp = {};
struct gdma_destroy_pd_req req = {};
struct mana_ib_dev *dev;
struct gdma_context *gc;
dev = container_of(ibdev, struct