Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 443b9a14 authored by Serge Semin's avatar Serge Semin Committed by Jon Mason
Browse files

NTB: Alter MW API to support multi-ports devices



Multi-port NTB devices permit to share a memory between all accessible peers.
Memory Windows API is altered to correspondingly initialize and map memory
windows for such devices:
 ntb_mw_count(pidx); - number of inbound memory windows, which can be allocated
for shared buffer with specified peer device.
 ntb_mw_get_align(pidx, widx); - get alignment and size restriction parameters
to properly allocate inbound memory region.
 ntb_peer_mw_count(); - get number of outbound memory windows.
 ntb_peer_mw_get_addr(widx); - get mapping address of an outbound memory window

If hardware supports inbound translation configured on the local ntb port:
 ntb_mw_set_trans(pidx, widx); - set translation address of allocated inbound
memory window so a peer device could access it.
 ntb_mw_clear_trans(pidx, widx); - clear the translation address of an inbound
memory window.

If hardware supports outbound translation configured on the peer ntb port:
 ntb_peer_mw_set_trans(pidx, widx); - set translation address of a memory
window retrieved from a peer device
 ntb_peer_mw_clear_trans(pidx, widx); - clear the translation address of an
outbound memory window

Signed-off-by: default avatarSerge Semin <fancer.lancer@gmail.com>
Acked-by: default avatarAllen Hubbe <Allen.Hubbe@dell.com>
Signed-off-by: default avatarJon Mason <jdmason@kudzu.us>
parent 4e8c11b7
Loading
Loading
Loading
Loading
+51 −17
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 *   GPL LICENSE SUMMARY
 *
 *   Copyright (C) 2016 Advanced Micro Devices, Inc. All Rights Reserved.
 *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of version 2 of the GNU General Public License as
@@ -13,6 +14,7 @@
 *   BSD LICENSE
 *
 *   Copyright (C) 2016 Advanced Micro Devices, Inc. All Rights Reserved.
 *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
@@ -79,40 +81,42 @@ static int ndev_mw_to_bar(struct amd_ntb_dev *ndev, int idx)
	return 1 << idx;
}

static int amd_ntb_mw_count(struct ntb_dev *ntb)
static int amd_ntb_mw_count(struct ntb_dev *ntb, int pidx)
{
	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	return ntb_ndev(ntb)->mw_count;
}

static int amd_ntb_mw_get_range(struct ntb_dev *ntb, int idx,
				phys_addr_t *base,
				resource_size_t *size,
				resource_size_t *align,
				resource_size_t *align_size)
static int amd_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx,
				resource_size_t *addr_align,
				resource_size_t *size_align,
				resource_size_t *size_max)
{
	struct amd_ntb_dev *ndev = ntb_ndev(ntb);
	int bar;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	bar = ndev_mw_to_bar(ndev, idx);
	if (bar < 0)
		return bar;

	if (base)
		*base = pci_resource_start(ndev->ntb.pdev, bar);

	if (size)
		*size = pci_resource_len(ndev->ntb.pdev, bar);
	if (addr_align)
		*addr_align = SZ_4K;

	if (align)
		*align = SZ_4K;
	if (size_align)
		*size_align = 1;

	if (align_size)
		*align_size = 1;
	if (size_max)
		*size_max = pci_resource_len(ndev->ntb.pdev, bar);

	return 0;
}

static int amd_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
static int amd_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
				dma_addr_t addr, resource_size_t size)
{
	struct amd_ntb_dev *ndev = ntb_ndev(ntb);
@@ -122,6 +126,9 @@ static int amd_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
	u64 base_addr, limit, reg_val;
	int bar;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	bar = ndev_mw_to_bar(ndev, idx);
	if (bar < 0)
		return bar;
@@ -284,6 +291,31 @@ static int amd_ntb_link_disable(struct ntb_dev *ntb)
	return 0;
}

static int amd_ntb_peer_mw_count(struct ntb_dev *ntb)
{
	/* The same as for inbound MWs */
	return ntb_ndev(ntb)->mw_count;
}

static int amd_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
				    phys_addr_t *base, resource_size_t *size)
{
	struct amd_ntb_dev *ndev = ntb_ndev(ntb);
	int bar;

	bar = ndev_mw_to_bar(ndev, idx);
	if (bar < 0)
		return bar;

	if (base)
		*base = pci_resource_start(ndev->ntb.pdev, bar);

	if (size)
		*size = pci_resource_len(ndev->ntb.pdev, bar);

	return 0;
}

static u64 amd_ntb_db_valid_mask(struct ntb_dev *ntb)
{
	return ntb_ndev(ntb)->db_valid_mask;
@@ -431,8 +463,10 @@ static int amd_ntb_peer_spad_write(struct ntb_dev *ntb,

static const struct ntb_dev_ops amd_ntb_ops = {
	.mw_count		= amd_ntb_mw_count,
	.mw_get_range		= amd_ntb_mw_get_range,
	.mw_get_align		= amd_ntb_mw_get_align,
	.mw_set_trans		= amd_ntb_mw_set_trans,
	.peer_mw_count		= amd_ntb_peer_mw_count,
	.peer_mw_get_addr	= amd_ntb_peer_mw_get_addr,
	.link_is_up		= amd_ntb_link_is_up,
	.link_enable		= amd_ntb_link_enable,
	.link_disable		= amd_ntb_link_disable,
+70 −20
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 *
 *   Copyright(c) 2012 Intel Corporation. All rights reserved.
 *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
 *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of version 2 of the GNU General Public License as
@@ -15,6 +16,7 @@
 *
 *   Copyright(c) 2012 Intel Corporation. All rights reserved.
 *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
 *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
@@ -1035,20 +1037,26 @@ static void ndev_deinit_debugfs(struct intel_ntb_dev *ndev)
	debugfs_remove_recursive(ndev->debugfs_dir);
}

static int intel_ntb_mw_count(struct ntb_dev *ntb)
static int intel_ntb_mw_count(struct ntb_dev *ntb, int pidx)
{
	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	return ntb_ndev(ntb)->mw_count;
}

static int intel_ntb_mw_get_range(struct ntb_dev *ntb, int idx,
				  phys_addr_t *base,
				  resource_size_t *size,
				  resource_size_t *align,
				  resource_size_t *align_size)
static int intel_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx,
				  resource_size_t *addr_align,
				  resource_size_t *size_align,
				  resource_size_t *size_max)
{
	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
	resource_size_t bar_size, mw_size;
	int bar;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
		idx += 1;

@@ -1056,24 +1064,26 @@ static int intel_ntb_mw_get_range(struct ntb_dev *ntb, int idx,
	if (bar < 0)
		return bar;

	if (base)
		*base = pci_resource_start(ndev->ntb.pdev, bar) +
			(idx == ndev->b2b_idx ? ndev->b2b_off : 0);
	bar_size = pci_resource_len(ndev->ntb.pdev, bar);

	if (size)
		*size = pci_resource_len(ndev->ntb.pdev, bar) -
			(idx == ndev->b2b_idx ? ndev->b2b_off : 0);
	if (idx == ndev->b2b_idx)
		mw_size = bar_size - ndev->b2b_off;
	else
		mw_size = bar_size;

	if (addr_align)
		*addr_align = pci_resource_len(ndev->ntb.pdev, bar);

	if (align)
		*align = pci_resource_len(ndev->ntb.pdev, bar);
	if (size_align)
		*size_align = 1;

	if (align_size)
		*align_size = 1;
	if (size_max)
		*size_max = mw_size;

	return 0;
}

static int intel_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
static int intel_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
				  dma_addr_t addr, resource_size_t size)
{
	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1083,6 +1093,9 @@ static int intel_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
	u64 base, limit, reg_val;
	int bar;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
		idx += 1;

@@ -1249,6 +1262,36 @@ static int intel_ntb_link_disable(struct ntb_dev *ntb)
	return 0;
}

static int intel_ntb_peer_mw_count(struct ntb_dev *ntb)
{
	/* Numbers of inbound and outbound memory windows match */
	return ntb_ndev(ntb)->mw_count;
}

static int intel_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
				     phys_addr_t *base, resource_size_t *size)
{
	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
	int bar;

	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
		idx += 1;

	bar = ndev_mw_to_bar(ndev, idx);
	if (bar < 0)
		return bar;

	if (base)
		*base = pci_resource_start(ndev->ntb.pdev, bar) +
			(idx == ndev->b2b_idx ? ndev->b2b_off : 0);

	if (size)
		*size = pci_resource_len(ndev->ntb.pdev, bar) -
			(idx == ndev->b2b_idx ? ndev->b2b_off : 0);

	return 0;
}

static int intel_ntb_db_is_unsafe(struct ntb_dev *ntb)
{
	return ndev_ignore_unsafe(ntb_ndev(ntb), NTB_UNSAFE_DB);
@@ -1902,7 +1945,7 @@ static int intel_ntb3_link_enable(struct ntb_dev *ntb,

	return 0;
}
static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int idx,
static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
				   dma_addr_t addr, resource_size_t size)
{
	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1912,6 +1955,9 @@ static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int idx,
	u64 base, limit, reg_val;
	int bar;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
		idx += 1;

@@ -2906,8 +2952,10 @@ static const struct intel_ntb_xlat_reg skx_sec_xlat = {
/* operations for primary side of local ntb */
static const struct ntb_dev_ops intel_ntb_ops = {
	.mw_count		= intel_ntb_mw_count,
	.mw_get_range		= intel_ntb_mw_get_range,
	.mw_get_align		= intel_ntb_mw_get_align,
	.mw_set_trans		= intel_ntb_mw_set_trans,
	.peer_mw_count		= intel_ntb_peer_mw_count,
	.peer_mw_get_addr	= intel_ntb_peer_mw_get_addr,
	.link_is_up		= intel_ntb_link_is_up,
	.link_enable		= intel_ntb_link_enable,
	.link_disable		= intel_ntb_link_disable,
@@ -2932,8 +2980,10 @@ static const struct ntb_dev_ops intel_ntb_ops = {

static const struct ntb_dev_ops intel_ntb3_ops = {
	.mw_count		= intel_ntb_mw_count,
	.mw_get_range		= intel_ntb_mw_get_range,
	.mw_get_align		= intel_ntb_mw_get_align,
	.mw_set_trans		= intel_ntb3_mw_set_trans,
	.peer_mw_count		= intel_ntb_peer_mw_count,
	.peer_mw_get_addr	= intel_ntb_peer_mw_get_addr,
	.link_is_up		= intel_ntb_link_is_up,
	.link_enable		= intel_ntb3_link_enable,
	.link_disable		= intel_ntb_link_disable,
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 *   GPL LICENSE SUMMARY
 *
 *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
 *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of version 2 of the GNU General Public License as
@@ -18,6 +19,7 @@
 *   BSD LICENSE
 *
 *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
 *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
+16 −5
Original line number Diff line number Diff line
@@ -673,7 +673,7 @@ static void ntb_free_mw(struct ntb_transport_ctx *nt, int num_mw)
	if (!mw->virt_addr)
		return;

	ntb_mw_clear_trans(nt->ndev, num_mw);
	ntb_mw_clear_trans(nt->ndev, PIDX, num_mw);
	dma_free_coherent(&pdev->dev, mw->buff_size,
			  mw->virt_addr, mw->dma_addr);
	mw->xlat_size = 0;
@@ -730,7 +730,8 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
	}

	/* Notify HW the memory location of the receive buffer */
	rc = ntb_mw_set_trans(nt->ndev, num_mw, mw->dma_addr, mw->xlat_size);
	rc = ntb_mw_set_trans(nt->ndev, PIDX, num_mw, mw->dma_addr,
			      mw->xlat_size);
	if (rc) {
		dev_err(&pdev->dev, "Unable to set mw%d translation", num_mw);
		ntb_free_mw(nt, num_mw);
@@ -1058,7 +1059,12 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
	int node;
	int rc, i;

	mw_count = ntb_mw_count(ndev);
	mw_count = ntb_mw_count(ndev, PIDX);

	if (!ndev->ops->mw_set_trans) {
		dev_err(&ndev->dev, "Inbound MW based NTB API is required\n");
		return -EINVAL;
	}

	if (ntb_db_is_unsafe(ndev))
		dev_dbg(&ndev->dev,
@@ -1100,8 +1106,13 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
	for (i = 0; i < mw_count; i++) {
		mw = &nt->mw_vec[i];

		rc = ntb_mw_get_range(ndev, i, &mw->phys_addr, &mw->phys_size,
				      &mw->xlat_align, &mw->xlat_align_size);
		rc = ntb_mw_get_align(ndev, PIDX, i, &mw->xlat_align,
				      &mw->xlat_align_size, NULL);
		if (rc)
			goto err1;

		rc = ntb_peer_mw_get_addr(ndev, i, &mw->phys_addr,
					  &mw->phys_size);
		if (rc)
			goto err1;

+13 −4
Original line number Diff line number Diff line
@@ -455,7 +455,7 @@ static void perf_free_mw(struct perf_ctx *perf)
	if (!mw->virt_addr)
		return;

	ntb_mw_clear_trans(perf->ntb, 0);
	ntb_mw_clear_trans(perf->ntb, PIDX, 0);
	dma_free_coherent(&pdev->dev, mw->buf_size,
			  mw->virt_addr, mw->dma_addr);
	mw->xlat_size = 0;
@@ -491,7 +491,7 @@ static int perf_set_mw(struct perf_ctx *perf, resource_size_t size)
		mw->buf_size = 0;
	}

	rc = ntb_mw_set_trans(perf->ntb, 0, mw->dma_addr, mw->xlat_size);
	rc = ntb_mw_set_trans(perf->ntb, PIDX, 0, mw->dma_addr, mw->xlat_size);
	if (rc) {
		dev_err(&perf->ntb->dev, "Unable to set mw0 translation\n");
		perf_free_mw(perf);
@@ -562,8 +562,12 @@ static int perf_setup_mw(struct ntb_dev *ntb, struct perf_ctx *perf)

	mw = &perf->mw;

	rc = ntb_mw_get_range(ntb, 0, &mw->phys_addr, &mw->phys_size,
			      &mw->xlat_align, &mw->xlat_align_size);
	rc = ntb_mw_get_align(ntb, PIDX, 0, &mw->xlat_align,
			      &mw->xlat_align_size, NULL);
	if (rc)
		return rc;

	rc = ntb_peer_mw_get_addr(ntb, 0, &mw->phys_addr, &mw->phys_size);
	if (rc)
		return rc;

@@ -767,6 +771,11 @@ static int perf_probe(struct ntb_client *client, struct ntb_dev *ntb)
		return -EIO;
	}

	if (!ntb->ops->mw_set_trans) {
		dev_err(&ntb->dev, "Need inbound MW based NTB API\n");
		return -EINVAL;
	}

	if (ntb_peer_port_count(ntb) != NTB_DEF_PEER_CNT)
		dev_warn(&ntb->dev, "Multi-port NTB devices unsupported\n");

Loading