From: Alexandre Bounine <alexandre.bounine@idt.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexandre Bounine <alexandre.bounine@idt.com>,
Matt Porter <mporter@kernel.crashing.org>,
Aurelien Jacquiot <a-jacquiot@ti.com>,
Andre van Herk <andre.van.herk@prodrive-technologies.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 05/30] rapidio/tsi721: add option to configure direct mapping of IB window
Date: Fri, 5 Feb 2016 18:19:21 -0500 [thread overview]
Message-ID: <1454714386-15259-6-git-send-email-alexandre.bounine@idt.com> (raw)
In-Reply-To: <1454714386-15259-1-git-send-email-alexandre.bounine@idt.com>
Add an option to configure mapping of Inbound Window without RIO-to-PCIe
address translation.
If a local memory buffer is not properly aligned to meet HW requirements
for RapidIO address mapping with address translation, caller can request
an inbound window with matching RapidIO address assigned to it.
This implementation selects RapidIO base address and size for inbound
window that are capable to accommodate the local memory buffer.
Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Cc: Aurelien Jacquiot <a-jacquiot@ti.com>
Cc: Andre van Herk <andre.van.herk@prodrive-technologies.com>
Cc: linux-kernel@vger.kernel.org
---
drivers/rapidio/devices/tsi721.c | 163 +++++++++++++++++++++++++++++++-------
drivers/rapidio/devices/tsi721.h | 9 ++-
2 files changed, 142 insertions(+), 30 deletions(-)
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index b96f0b9..d463d2c 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -888,71 +888,145 @@ static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart,
int i, avail = -1;
u32 regval;
struct tsi721_ib_win *ib_win;
+ bool direct = (lstart == rstart);
+ u64 ibw_size;
+ dma_addr_t loc_start;
+ u64 ibw_start;
+ struct tsi721_ib_win_mapping *map = NULL;
int ret = -EBUSY;
- if (!is_power_of_2(size) || size < 0x1000 ||
- ((u64)lstart & (size - 1)) || (rstart & (size - 1)))
- return -EINVAL;
+ if (direct) {
+ dev_dbg(&priv->pdev->dev,
+ "Direct (RIO_0x%llx -> PCIe_0x%pad), size=0x%x",
+ rstart, &lstart, size);
+
+ /* Calculate minimal acceptable window size and base address */
+
+ ibw_size = roundup_pow_of_two(size);
+ ibw_start = lstart & ~(ibw_size - 1);
+
+ while ((lstart + size) > (ibw_start + ibw_size)) {
+ ibw_size *= 2;
+ ibw_start = lstart & ~(ibw_size - 1);
+ if (ibw_size > 0x80000000) { /* Limit max size to 2GB */
+ return -EBUSY;
+ }
+ }
+
+ loc_start = ibw_start;
+
+ map = kzalloc(sizeof(struct tsi721_ib_win_mapping), GFP_ATOMIC);
+ if (map == NULL)
+ return -ENOMEM;
+
+ } else {
+ dev_dbg(&priv->pdev->dev,
+ "Translated (RIO_0x%llx -> PCIe_0x%pad), size=0x%x",
+ rstart, &lstart, size);
+
+ if (!is_power_of_2(size) || size < 0x1000 ||
+ ((u64)lstart & (size - 1)) || (rstart & (size - 1)))
+ return -EINVAL;
+ if (priv->ibwin_cnt == 0)
+ return -EBUSY;
+ ibw_start = rstart;
+ ibw_size = size;
+ loc_start = lstart;
+ }
- spin_lock(&priv->win_lock);
/*
* Scan for overlapping with active regions and mark the first available
* IB window at the same time.
*/
for (i = 0; i < TSI721_IBWIN_NUM; i++) {
ib_win = &priv->ib_win[i];
+
if (!ib_win->active) {
if (avail == -1) {
avail = i;
ret = 0;
}
- } else if (rstart < (ib_win->rstart + ib_win->size) &&
- (rstart + size) > ib_win->rstart) {
+ } else if (ibw_start < (ib_win->rstart + ib_win->size) &&
+ (ibw_start + ibw_size) > ib_win->rstart) {
+ /* Return error if address translation involved */
+ if (direct && ib_win->xlat) {
+ ret = -EFAULT;
+ break;
+ }
+
+ /*
+ * Direct mappings usually are larger than originally
+ * requested fragments - check if this new request fits
+ * into it.
+ */
+ if (rstart >= ib_win->rstart &&
+ (rstart + size) <= (ib_win->rstart +
+ ib_win->size)) {
+ /* We are in - no further mapping required */
+ map->lstart = lstart;
+ list_add_tail(&map->node, &ib_win->mappings);
+ return 0;
+ }
+
ret = -EFAULT;
break;
}
}
if (ret)
- goto err_out;
+ goto out;
i = avail;
/* Sanity check: available IB window must be disabled at this point */
regval = ioread32(priv->regs + TSI721_IBWIN_LB(i));
if (WARN_ON(regval & TSI721_IBWIN_LB_WEN)) {
ret = -EIO;
- goto err_out;
+ goto out;
}
ib_win = &priv->ib_win[i];
ib_win->active = true;
- ib_win->rstart = rstart;
- ib_win->lstart = lstart;
- ib_win->size = size;
- spin_unlock(&priv->win_lock);
+ ib_win->rstart = ibw_start;
+ ib_win->lstart = loc_start;
+ ib_win->size = ibw_size;
+ ib_win->xlat = (lstart != rstart);
+ INIT_LIST_HEAD(&ib_win->mappings);
- iowrite32(TSI721_IBWIN_SIZE(size) << 8,
+ /*
+ * When using direct IBW mapping and have larger than requested IBW size
+ * we can have multiple local memory blocks mapped through the same IBW
+ * To handle this situation we maintain list of "clients" for such IBWs.
+ */
+ if (direct) {
+ map->lstart = lstart;
+ list_add_tail(&map->node, &ib_win->mappings);
+ }
+
+ iowrite32(TSI721_IBWIN_SIZE(ibw_size) << 8,
priv->regs + TSI721_IBWIN_SZ(i));
- iowrite32(((u64)lstart >> 32), priv->regs + TSI721_IBWIN_TUA(i));
- iowrite32(((u64)lstart & TSI721_IBWIN_TLA_ADD),
+ iowrite32(((u64)loc_start >> 32), priv->regs + TSI721_IBWIN_TUA(i));
+ iowrite32(((u64)loc_start & TSI721_IBWIN_TLA_ADD),
priv->regs + TSI721_IBWIN_TLA(i));
- iowrite32(rstart >> 32, priv->regs + TSI721_IBWIN_UB(i));
- iowrite32((rstart & TSI721_IBWIN_LB_BA) | TSI721_IBWIN_LB_WEN,
+ iowrite32(ibw_start >> 32, priv->regs + TSI721_IBWIN_UB(i));
+ iowrite32((ibw_start & TSI721_IBWIN_LB_BA) | TSI721_IBWIN_LB_WEN,
priv->regs + TSI721_IBWIN_LB(i));
+
+ priv->ibwin_cnt--;
+
dev_dbg(&priv->pdev->dev,
- "Configured IBWIN%d mapping (RIO_0x%llx -> PCIe_0x%llx)\n",
- i, rstart, (unsigned long long)lstart);
+ "Configured IBWIN%d (RIO_0x%llx -> PCIe_0x%llx), size=0x%llx\n",
+ i, ibw_start, (unsigned long long)loc_start, ibw_size);
return 0;
-err_out:
- spin_unlock(&priv->win_lock);
+out:
+ kfree(map);
return ret;
}
/**
- * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region.
+ * tsi721_rio_unmap_inb_mem -- Unmapping inbound memory region.
* @mport: RapidIO master port
* @lstart: Local memory space start address.
*/
@@ -963,22 +1037,53 @@ static void tsi721_rio_unmap_inb_mem(struct rio_mport *mport,
struct tsi721_ib_win *ib_win;
int i;
+ dev_dbg(&priv->pdev->dev,
+ "Unmap IBW mapped to PCIe_0x%pad", &lstart);
+
/* Search for matching active inbound translation window */
- spin_lock(&priv->win_lock);
for (i = 0; i < TSI721_IBWIN_NUM; i++) {
ib_win = &priv->ib_win[i];
- if (ib_win->active && ib_win->lstart == lstart) {
+
+ /* Address translating IBWs must to be an exact march */
+ if (!ib_win->active ||
+ (ib_win->xlat && lstart != ib_win->lstart))
+ continue;
+
+ if (lstart >= ib_win->lstart &&
+ lstart < (ib_win->lstart + ib_win->size)) {
+
+ if (!ib_win->xlat) {
+ struct tsi721_ib_win_mapping *map;
+ int found = 0;
+
+ list_for_each_entry(map,
+ &ib_win->mappings, node) {
+ if (map->lstart == lstart) {
+ list_del(&map->node);
+ kfree(map);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ continue;
+
+ if (!list_empty(&ib_win->mappings))
+ break;
+ }
+
+ dev_dbg(&priv->pdev->dev, "Disable IBWIN_%d", i);
iowrite32(0, priv->regs + TSI721_IBWIN_LB(i));
ib_win->active = false;
+ priv->ibwin_cnt++;
break;
}
}
- spin_unlock(&priv->win_lock);
if (i == TSI721_IBWIN_NUM)
- dev_err(&priv->pdev->dev,
- "IB window mapped to %llx not found\n",
- (unsigned long long)lstart);
+ dev_dbg(&priv->pdev->dev,
+ "IB window mapped to %pad not found", &lstart);
}
/**
@@ -995,7 +1100,7 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv)
/* Disable all SR2PC inbound windows */
for (i = 0; i < TSI721_IBWIN_NUM; i++)
iowrite32(0, priv->regs + TSI721_IBWIN_LB(i));
- spin_lock_init(&priv->win_lock);
+ priv->ibwin_cnt = TSI721_IBWIN_NUM;
}
/**
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index 355f356..f81d011 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -808,11 +808,18 @@ struct msix_irq {
};
#endif /* CONFIG_PCI_MSI */
+struct tsi721_ib_win_mapping {
+ struct list_head node;
+ dma_addr_t lstart;
+};
+
struct tsi721_ib_win {
u64 rstart;
u32 size;
dma_addr_t lstart;
bool active;
+ bool xlat;
+ struct list_head mappings;
};
struct tsi721_device {
@@ -853,7 +860,7 @@ struct tsi721_device {
/* Inbound Mapping Windows */
struct tsi721_ib_win ib_win[TSI721_IBWIN_NUM];
- spinlock_t win_lock;
+ int ibwin_cnt;
};
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
--
1.7.8.4
next prev parent reply other threads:[~2016-02-05 23:32 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-05 23:19 [PATCH 00/30] rapidio: mport character driver and subsystem updates Alexandre Bounine
2016-02-05 23:19 ` [PATCH 01/30] rapidio/rionet: fix deadlock on SMP Alexandre Bounine
2016-02-05 23:19 ` [PATCH 02/30] rapidio/rionet: add capability to change MTU Alexandre Bounine
2016-02-05 23:19 ` [PATCH 03/30] rapidio/tsi721: fix hardcoded MRRS setting Alexandre Bounine
2016-02-05 23:19 ` [PATCH 04/30] rapidio/tsi721: add check for overlapped IB window mappings Alexandre Bounine
2016-02-05 23:19 ` Alexandre Bounine [this message]
2016-02-05 23:19 ` [PATCH 06/30] rapidio/tsi721_dma: fix pending transaction queue handling Alexandre Bounine
2016-02-05 23:19 ` [PATCH 07/30] rapidio: add query_mport operation Alexandre Bounine
2016-02-05 23:19 ` [PATCH 08/30] rapidio/tsi721: add query_mport callback Alexandre Bounine
2016-02-05 23:19 ` [PATCH 09/30] rapidio: add shutdown notification for RapidIO devices Alexandre Bounine
2016-02-05 23:19 ` [PATCH 10/30] rapidio/tsi721: add shutdown notification callback Alexandre Bounine
2016-02-05 23:19 ` [PATCH 11/30] rapidio/rionet: add shutdown event handling Alexandre Bounine
2016-02-05 23:19 ` [PATCH 12/30] rapidio: rework common RIO device add/delete routines Alexandre Bounine
2016-02-05 23:19 ` [PATCH 13/30] rapidio: move net allocation into core code Alexandre Bounine
2016-02-05 23:19 ` [PATCH 14/30] rapidio: add core mport removal support Alexandre Bounine
2016-02-05 23:19 ` [PATCH 15/30] rapidio/tsi721: add HW specific mport removal Alexandre Bounine
2016-02-05 23:19 ` [PATCH 16/30] powerpc/fsl_rio: changes to mport registration Alexandre Bounine
2016-02-05 23:19 ` [PATCH 17/30] rapidio/rionet: add locking into add/remove device Alexandre Bounine
2016-02-05 23:19 ` [PATCH 18/30] rapidio/rionet: add mport removal handling Alexandre Bounine
2016-02-05 23:19 ` [PATCH 19/30] rapidio: add lock protection for doorbell list Alexandre Bounine
2016-02-05 23:19 ` [PATCH 20/30] rapidio: move rio_local_set_device_id function to the common core Alexandre Bounine
2016-02-05 23:19 ` [PATCH 21/30] rapidio: move rio_pw_enable into core code Alexandre Bounine
2016-02-05 23:19 ` [PATCH 22/30] rapidio: add global inbound port write interfaces Alexandre Bounine
2016-02-08 21:18 ` Andrew Morton
2016-02-09 13:56 ` Bounine, Alexandre
2016-02-05 23:19 ` [PATCH 23/30] rapidio/tsi721: fix locking in OB_MSG processing Alexandre Bounine
2016-02-05 23:19 ` [PATCH 24/30] rapidio: add outbound window support Alexandre Bounine
2016-02-05 23:19 ` [PATCH 25/30] rapidio/tsi721: add outbound windows mapping support Alexandre Bounine
2016-02-05 23:19 ` [PATCH 26/30] rapidio/tsi721: add filtered debug output Alexandre Bounine
2016-02-05 23:19 ` [PATCH 27/30] rapidio/tsi721_dma: update error reporting from prep_sg callback Alexandre Bounine
2016-02-05 23:19 ` [PATCH 28/30] rapidio/tsi721_dma: fix synchronization issues Alexandre Bounine
2016-02-05 23:19 ` [PATCH 29/30] rapidio/tsi721_dma: fix hardware error handling Alexandre Bounine
2016-02-05 23:19 ` [PATCH 30/30] rapidio: add mport char device driver Alexandre Bounine
2016-04-05 10:36 ` Gabriel Laskar
2016-04-05 11:45 ` Bounine, Alexandre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1454714386-15259-6-git-send-email-alexandre.bounine@idt.com \
--to=alexandre.bounine@idt.com \
--cc=a-jacquiot@ti.com \
--cc=akpm@linux-foundation.org \
--cc=andre.van.herk@prodrive-technologies.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mporter@kernel.crashing.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®