aboutsummaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/bnxt_re/qplib_res.c
diff options
context:
space:
mode:
authorGravatar Selvin Xavier <selvin.xavier@broadcom.com> 2023-06-13 11:12:22 -0700
committerGravatar Jason Gunthorpe <jgg@nvidia.com> 2023-06-21 14:13:17 -0300
commit0ac20faf5d837b59fb4c041ea320932ed47fd67f (patch)
tree8b12469954ba74d0743c0bb5146514144490ac12 /drivers/infiniband/hw/bnxt_re/qplib_res.c
parentRDMA/bnxt_re: Move the interface version to chip context structure (diff)
downloadlinux-0ac20faf5d837b59fb4c041ea320932ed47fd67f.tar.gz
linux-0ac20faf5d837b59fb4c041ea320932ed47fd67f.tar.bz2
linux-0ac20faf5d837b59fb4c041ea320932ed47fd67f.zip
RDMA/bnxt_re: Reorg the bar mapping
Reorganize the code for allocation and mapping of Doorbell pages. Implements new HW command to get the BAR length used by L2 driver. These changes are used by the future patch which maps the WC Doorbell pages. Also, introduced a new lock dpi_tbl_lock for synchronize the DB page allocation from users. Link: https://lore.kernel.org/r/1686679943-17117-7-git-send-email-selvin.xavier@broadcom.com Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Diffstat (limited to 'drivers/infiniband/hw/bnxt_re/qplib_res.c')
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c174
1 files changed, 113 insertions, 61 deletions
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index 920ab8704c8b..e1cbe594e56b 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -704,44 +704,73 @@ static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res,
}
/* DPIs */
-int bnxt_qplib_alloc_dpi(struct bnxt_qplib_dpi_tbl *dpit,
- struct bnxt_qplib_dpi *dpi,
- void *app)
+int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
+ struct bnxt_qplib_dpi *dpi,
+ void *app, u8 type)
{
+ struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl;
+ struct bnxt_qplib_reg_desc *reg;
u32 bit_num;
+ u64 umaddr;
+
+ reg = &dpit->wcreg;
+ mutex_lock(&res->dpi_tbl_lock);
bit_num = find_first_bit(dpit->tbl, dpit->max);
- if (bit_num == dpit->max)
+ if (bit_num == dpit->max) {
+ mutex_unlock(&res->dpi_tbl_lock);
return -ENOMEM;
+ }
/* Found unused DPI */
clear_bit(bit_num, dpit->tbl);
dpit->app_tbl[bit_num] = app;
- dpi->dpi = bit_num;
- dpi->dbr = dpit->dbr_bar_reg_iomem + (bit_num * PAGE_SIZE);
- dpi->umdbr = dpit->unmapped_dbr + (bit_num * PAGE_SIZE);
+ dpi->bit = bit_num;
+ dpi->dpi = bit_num + (reg->offset - dpit->ucreg.offset) / PAGE_SIZE;
+
+ umaddr = reg->bar_base + reg->offset + bit_num * PAGE_SIZE;
+ dpi->umdbr = umaddr;
+
+ switch (type) {
+ case BNXT_QPLIB_DPI_TYPE_KERNEL:
+ /* priviledged dbr was already mapped just initialize it. */
+ dpi->umdbr = dpit->ucreg.bar_base +
+ dpit->ucreg.offset + bit_num * PAGE_SIZE;
+ dpi->dbr = dpit->priv_db;
+ dpi->dpi = dpi->bit;
+ break;
+ default:
+ dpi->dbr = ioremap(umaddr, PAGE_SIZE);
+ break;
+ }
+ dpi->type = type;
+ mutex_unlock(&res->dpi_tbl_lock);
return 0;
+
}
int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
- struct bnxt_qplib_dpi_tbl *dpit,
- struct bnxt_qplib_dpi *dpi)
+ struct bnxt_qplib_dpi *dpi)
{
- if (dpi->dpi >= dpit->max) {
- dev_warn(&res->pdev->dev, "Invalid DPI? dpi = %d\n", dpi->dpi);
- return -EINVAL;
- }
- if (test_and_set_bit(dpi->dpi, dpit->tbl)) {
- dev_warn(&res->pdev->dev, "Freeing an unused DPI? dpi = %d\n",
- dpi->dpi);
+ struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl;
+
+ mutex_lock(&res->dpi_tbl_lock);
+ if (dpi->dpi && dpi->type != BNXT_QPLIB_DPI_TYPE_KERNEL)
+ pci_iounmap(res->pdev, dpi->dbr);
+
+ if (test_and_set_bit(dpi->bit, dpit->tbl)) {
+ dev_warn(&res->pdev->dev,
+ "Freeing an unused DPI? dpi = %d, bit = %d\n",
+ dpi->dpi, dpi->bit);
+ mutex_unlock(&res->dpi_tbl_lock);
return -EINVAL;
}
if (dpit->app_tbl)
- dpit->app_tbl[dpi->dpi] = NULL;
+ dpit->app_tbl[dpi->bit] = NULL;
memset(dpi, 0, sizeof(*dpi));
-
+ mutex_unlock(&res->dpi_tbl_lock);
return 0;
}
@@ -750,52 +779,38 @@ static void bnxt_qplib_free_dpi_tbl(struct bnxt_qplib_res *res,
{
kfree(dpit->tbl);
kfree(dpit->app_tbl);
- if (dpit->dbr_bar_reg_iomem)
- pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
- memset(dpit, 0, sizeof(*dpit));
+ dpit->tbl = NULL;
+ dpit->app_tbl = NULL;
+ dpit->max = 0;
}
-static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
- struct bnxt_qplib_dpi_tbl *dpit,
- u32 dbr_offset)
+static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
+ struct bnxt_qplib_dev_attr *dev_attr)
{
- u32 dbr_bar_reg = RCFW_DBR_PCI_BAR_REGION;
- resource_size_t bar_reg_base;
- u32 dbr_len, bytes;
-
- if (dpit->dbr_bar_reg_iomem) {
- dev_err(&res->pdev->dev, "DBR BAR region %d already mapped\n",
- dbr_bar_reg);
- return -EALREADY;
- }
-
- bar_reg_base = pci_resource_start(res->pdev, dbr_bar_reg);
- if (!bar_reg_base) {
- dev_err(&res->pdev->dev, "BAR region %d resc start failed\n",
- dbr_bar_reg);
- return -ENOMEM;
- }
+ struct bnxt_qplib_dpi_tbl *dpit;
+ struct bnxt_qplib_reg_desc *reg;
+ unsigned long bar_len;
+ u32 dbr_offset;
+ u32 bytes;
- dbr_len = pci_resource_len(res->pdev, dbr_bar_reg) - dbr_offset;
- if (!dbr_len || ((dbr_len & (PAGE_SIZE - 1)) != 0)) {
- dev_err(&res->pdev->dev, "Invalid DBR length %d\n", dbr_len);
- return -ENOMEM;
- }
+ dpit = &res->dpi_tbl;
+ reg = &dpit->wcreg;
- dpit->dbr_bar_reg_iomem = ioremap(bar_reg_base + dbr_offset,
- dbr_len);
- if (!dpit->dbr_bar_reg_iomem) {
- dev_err(&res->pdev->dev,
- "FP: DBR BAR region %d mapping failed\n", dbr_bar_reg);
- return -ENOMEM;
+ if (!bnxt_qplib_is_chip_gen_p5(res->cctx)) {
+ /* Offest should come from L2 driver */
+ dbr_offset = dev_attr->l2_db_size;
+ dpit->ucreg.offset = dbr_offset;
+ dpit->wcreg.offset = dbr_offset;
}
- dpit->unmapped_dbr = bar_reg_base + dbr_offset;
- dpit->max = dbr_len / PAGE_SIZE;
+ bar_len = pci_resource_len(res->pdev, reg->bar_id);
+ dpit->max = (bar_len - reg->offset) / PAGE_SIZE;
+ if (dev_attr->max_dpi)
+ dpit->max = min_t(u32, dpit->max, dev_attr->max_dpi);
- dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL);
+ dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL);
if (!dpit->app_tbl)
- goto unmap_io;
+ return -ENOMEM;
bytes = dpit->max >> 3;
if (!bytes)
@@ -805,17 +820,14 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res,
if (!dpit->tbl) {
kfree(dpit->app_tbl);
dpit->app_tbl = NULL;
- goto unmap_io;
+ return -ENOMEM;
}
memset((u8 *)dpit->tbl, 0xFF, bytes);
+ dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset;
return 0;
-unmap_io:
- iounmap(dpit->dbr_bar_reg_iomem);
- dpit->dbr_bar_reg_iomem = NULL;
- return -ENOMEM;
}
/* Stats */
@@ -882,7 +894,7 @@ int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev,
if (rc)
goto fail;
- rc = bnxt_qplib_alloc_dpi_tbl(res, &res->dpi_tbl, dev_attr->l2_db_size);
+ rc = bnxt_qplib_alloc_dpi_tbl(res, dev_attr);
if (rc)
goto fail;
@@ -892,6 +904,46 @@ fail:
return rc;
}
+void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res)
+{
+ struct bnxt_qplib_reg_desc *reg;
+
+ reg = &res->dpi_tbl.ucreg;
+ if (reg->bar_reg)
+ pci_iounmap(res->pdev, reg->bar_reg);
+ reg->bar_reg = NULL;
+ reg->bar_base = 0;
+ reg->len = 0;
+ reg->bar_id = 0;
+}
+
+int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res)
+{
+ struct bnxt_qplib_reg_desc *ucreg;
+ struct bnxt_qplib_reg_desc *wcreg;
+
+ wcreg = &res->dpi_tbl.wcreg;
+ wcreg->bar_id = RCFW_DBR_PCI_BAR_REGION;
+ wcreg->bar_base = pci_resource_start(res->pdev, wcreg->bar_id);
+
+ ucreg = &res->dpi_tbl.ucreg;
+ ucreg->bar_id = RCFW_DBR_PCI_BAR_REGION;
+ ucreg->bar_base = pci_resource_start(res->pdev, ucreg->bar_id);
+ ucreg->len = ucreg->offset + PAGE_SIZE;
+ if (!ucreg->len || ((ucreg->len & (PAGE_SIZE - 1)) != 0)) {
+ dev_err(&res->pdev->dev, "QPLIB: invalid dbr length %d",
+ (int)ucreg->len);
+ return -EINVAL;
+ }
+ ucreg->bar_reg = ioremap(ucreg->bar_base, ucreg->len);
+ if (!ucreg->bar_reg) {
+ dev_err(&res->pdev->dev, "priviledged dpi map failed!");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
int bnxt_qplib_determine_atomics(struct pci_dev *dev)
{
int comp;