18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license.  When using or
38c2ecf20Sopenharmony_ci *   redistributing this file, you may do so under either license.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *   GPL LICENSE SUMMARY
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *   Copyright(c) 2012 Intel Corporation. All rights reserved.
88c2ecf20Sopenharmony_ci *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
98c2ecf20Sopenharmony_ci *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *   This program is free software; you can redistribute it and/or modify
128c2ecf20Sopenharmony_ci *   it under the terms of version 2 of the GNU General Public License as
138c2ecf20Sopenharmony_ci *   published by the Free Software Foundation.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci *   BSD LICENSE
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *   Copyright(c) 2012 Intel Corporation. All rights reserved.
188c2ecf20Sopenharmony_ci *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
198c2ecf20Sopenharmony_ci *   Copyright (C) 2016 T-Platforms. All Rights Reserved.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci *   Redistribution and use in source and binary forms, with or without
228c2ecf20Sopenharmony_ci *   modification, are permitted provided that the following conditions
238c2ecf20Sopenharmony_ci *   are met:
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci *     * Redistributions of source code must retain the above copyright
268c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer.
278c2ecf20Sopenharmony_ci *     * Redistributions in binary form must reproduce the above copy
288c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer in
298c2ecf20Sopenharmony_ci *       the documentation and/or other materials provided with the
308c2ecf20Sopenharmony_ci *       distribution.
318c2ecf20Sopenharmony_ci *     * Neither the name of Intel Corporation nor the names of its
328c2ecf20Sopenharmony_ci *       contributors may be used to endorse or promote products derived
338c2ecf20Sopenharmony_ci *       from this software without specific prior written permission.
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
368c2ecf20Sopenharmony_ci *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
378c2ecf20Sopenharmony_ci *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
388c2ecf20Sopenharmony_ci *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
398c2ecf20Sopenharmony_ci *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
408c2ecf20Sopenharmony_ci *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
418c2ecf20Sopenharmony_ci *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
428c2ecf20Sopenharmony_ci *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
438c2ecf20Sopenharmony_ci *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
448c2ecf20Sopenharmony_ci *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
458c2ecf20Sopenharmony_ci *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
468c2ecf20Sopenharmony_ci *
478c2ecf20Sopenharmony_ci * Intel PCIe NTB Linux driver
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
518c2ecf20Sopenharmony_ci#include <linux/delay.h>
528c2ecf20Sopenharmony_ci#include <linux/init.h>
538c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
548c2ecf20Sopenharmony_ci#include <linux/module.h>
558c2ecf20Sopenharmony_ci#include <linux/pci.h>
568c2ecf20Sopenharmony_ci#include <linux/random.h>
578c2ecf20Sopenharmony_ci#include <linux/slab.h>
588c2ecf20Sopenharmony_ci#include <linux/ntb.h>
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#include "ntb_hw_intel.h"
618c2ecf20Sopenharmony_ci#include "ntb_hw_gen1.h"
628c2ecf20Sopenharmony_ci#include "ntb_hw_gen3.h"
638c2ecf20Sopenharmony_ci#include "ntb_hw_gen4.h"
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define NTB_NAME	"ntb_hw_intel"
668c2ecf20Sopenharmony_ci#define NTB_DESC	"Intel(R) PCI-E Non-Transparent Bridge Driver"
678c2ecf20Sopenharmony_ci#define NTB_VER		"2.0"
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(NTB_DESC);
708c2ecf20Sopenharmony_ciMODULE_VERSION(NTB_VER);
718c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
728c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel Corporation");
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define bar0_off(base, bar) ((base) + ((bar) << 2))
758c2ecf20Sopenharmony_ci#define bar2_off(base, bar) bar0_off(base, (bar) - 2)
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic const struct intel_ntb_reg xeon_reg;
788c2ecf20Sopenharmony_cistatic const struct intel_ntb_alt_reg xeon_pri_reg;
798c2ecf20Sopenharmony_cistatic const struct intel_ntb_alt_reg xeon_sec_reg;
808c2ecf20Sopenharmony_cistatic const struct intel_ntb_alt_reg xeon_b2b_reg;
818c2ecf20Sopenharmony_cistatic const struct intel_ntb_xlat_reg xeon_pri_xlat;
828c2ecf20Sopenharmony_cistatic const struct intel_ntb_xlat_reg xeon_sec_xlat;
838c2ecf20Sopenharmony_cistatic const struct ntb_dev_ops intel_ntb_ops;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic const struct file_operations intel_ntb_debugfs_info;
868c2ecf20Sopenharmony_cistatic struct dentry *debugfs_dir;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic int b2b_mw_idx = -1;
898c2ecf20Sopenharmony_cimodule_param(b2b_mw_idx, int, 0644);
908c2ecf20Sopenharmony_ciMODULE_PARM_DESC(b2b_mw_idx, "Use this mw idx to access the peer ntb.  A "
918c2ecf20Sopenharmony_ci		 "value of zero or positive starts from first mw idx, and a "
928c2ecf20Sopenharmony_ci		 "negative value starts from last mw idx.  Both sides MUST "
938c2ecf20Sopenharmony_ci		 "set the same value here!");
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic unsigned int b2b_mw_share;
968c2ecf20Sopenharmony_cimodule_param(b2b_mw_share, uint, 0644);
978c2ecf20Sopenharmony_ciMODULE_PARM_DESC(b2b_mw_share, "If the b2b mw is large enough, configure the "
988c2ecf20Sopenharmony_ci		 "ntb so that the peer ntb only occupies the first half of "
998c2ecf20Sopenharmony_ci		 "the mw, so the second half can still be used as a mw.  Both "
1008c2ecf20Sopenharmony_ci		 "sides MUST set the same value here!");
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_usd_bar2_addr64,
1038c2ecf20Sopenharmony_ci		   xeon_b2b_usd_addr.bar2_addr64, ullong, 0644);
1048c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_usd_bar2_addr64,
1058c2ecf20Sopenharmony_ci		 "XEON B2B USD BAR 2 64-bit address");
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_usd_bar4_addr64,
1088c2ecf20Sopenharmony_ci		   xeon_b2b_usd_addr.bar4_addr64, ullong, 0644);
1098c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_usd_bar4_addr64,
1108c2ecf20Sopenharmony_ci		 "XEON B2B USD BAR 4 64-bit address");
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_usd_bar4_addr32,
1138c2ecf20Sopenharmony_ci		   xeon_b2b_usd_addr.bar4_addr32, ullong, 0644);
1148c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_usd_bar4_addr32,
1158c2ecf20Sopenharmony_ci		 "XEON B2B USD split-BAR 4 32-bit address");
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_usd_bar5_addr32,
1188c2ecf20Sopenharmony_ci		   xeon_b2b_usd_addr.bar5_addr32, ullong, 0644);
1198c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_usd_bar5_addr32,
1208c2ecf20Sopenharmony_ci		 "XEON B2B USD split-BAR 5 32-bit address");
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_dsd_bar2_addr64,
1238c2ecf20Sopenharmony_ci		   xeon_b2b_dsd_addr.bar2_addr64, ullong, 0644);
1248c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_dsd_bar2_addr64,
1258c2ecf20Sopenharmony_ci		 "XEON B2B DSD BAR 2 64-bit address");
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_dsd_bar4_addr64,
1288c2ecf20Sopenharmony_ci		   xeon_b2b_dsd_addr.bar4_addr64, ullong, 0644);
1298c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_dsd_bar4_addr64,
1308c2ecf20Sopenharmony_ci		 "XEON B2B DSD BAR 4 64-bit address");
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_dsd_bar4_addr32,
1338c2ecf20Sopenharmony_ci		   xeon_b2b_dsd_addr.bar4_addr32, ullong, 0644);
1348c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_dsd_bar4_addr32,
1358c2ecf20Sopenharmony_ci		 "XEON B2B DSD split-BAR 4 32-bit address");
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cimodule_param_named(xeon_b2b_dsd_bar5_addr32,
1388c2ecf20Sopenharmony_ci		   xeon_b2b_dsd_addr.bar5_addr32, ullong, 0644);
1398c2ecf20Sopenharmony_ciMODULE_PARM_DESC(xeon_b2b_dsd_bar5_addr32,
1408c2ecf20Sopenharmony_ci		 "XEON B2B DSD split-BAR 5 32-bit address");
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic int xeon_init_isr(struct intel_ntb_dev *ndev);
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic inline void ndev_reset_unsafe_flags(struct intel_ntb_dev *ndev)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	ndev->unsafe_flags = 0;
1488c2ecf20Sopenharmony_ci	ndev->unsafe_flags_ignore = 0;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	/* Only B2B has a workaround to avoid SDOORBELL */
1518c2ecf20Sopenharmony_ci	if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP)
1528c2ecf20Sopenharmony_ci		if (!ntb_topo_is_b2b(ndev->ntb.topo))
1538c2ecf20Sopenharmony_ci			ndev->unsafe_flags |= NTB_UNSAFE_DB;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	/* No low level workaround to avoid SB01BASE */
1568c2ecf20Sopenharmony_ci	if (ndev->hwerr_flags & NTB_HWERR_SB01BASE_LOCKUP) {
1578c2ecf20Sopenharmony_ci		ndev->unsafe_flags |= NTB_UNSAFE_DB;
1588c2ecf20Sopenharmony_ci		ndev->unsafe_flags |= NTB_UNSAFE_SPAD;
1598c2ecf20Sopenharmony_ci	}
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic inline int ndev_is_unsafe(struct intel_ntb_dev *ndev,
1638c2ecf20Sopenharmony_ci				 unsigned long flag)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	return !!(flag & ndev->unsafe_flags & ~ndev->unsafe_flags_ignore);
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic inline int ndev_ignore_unsafe(struct intel_ntb_dev *ndev,
1698c2ecf20Sopenharmony_ci				     unsigned long flag)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	flag &= ndev->unsafe_flags;
1728c2ecf20Sopenharmony_ci	ndev->unsafe_flags_ignore |= flag;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	return !!flag;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ciint ndev_mw_to_bar(struct intel_ntb_dev *ndev, int idx)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	if (idx < 0 || idx >= ndev->mw_count)
1808c2ecf20Sopenharmony_ci		return -EINVAL;
1818c2ecf20Sopenharmony_ci	return ndev->reg->mw_bar[idx];
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_civoid ndev_db_addr(struct intel_ntb_dev *ndev,
1858c2ecf20Sopenharmony_ci			       phys_addr_t *db_addr, resource_size_t *db_size,
1868c2ecf20Sopenharmony_ci			       phys_addr_t reg_addr, unsigned long reg)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
1898c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe doorbell access", __func__);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (db_addr) {
1928c2ecf20Sopenharmony_ci		*db_addr = reg_addr + reg;
1938c2ecf20Sopenharmony_ci		dev_dbg(&ndev->ntb.pdev->dev, "Peer db addr %llx\n", *db_addr);
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (db_size) {
1978c2ecf20Sopenharmony_ci		*db_size = ndev->reg->db_size;
1988c2ecf20Sopenharmony_ci		dev_dbg(&ndev->ntb.pdev->dev, "Peer db size %llx\n", *db_size);
1998c2ecf20Sopenharmony_ci	}
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciu64 ndev_db_read(struct intel_ntb_dev *ndev,
2038c2ecf20Sopenharmony_ci			       void __iomem *mmio)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
2068c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe doorbell access", __func__);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	return ndev->reg->db_ioread(mmio);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ciint ndev_db_write(struct intel_ntb_dev *ndev, u64 db_bits,
2128c2ecf20Sopenharmony_ci				void __iomem *mmio)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
2158c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe doorbell access", __func__);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if (db_bits & ~ndev->db_valid_mask)
2188c2ecf20Sopenharmony_ci		return -EINVAL;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	ndev->reg->db_iowrite(db_bits, mmio);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	return 0;
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic inline int ndev_db_set_mask(struct intel_ntb_dev *ndev, u64 db_bits,
2268c2ecf20Sopenharmony_ci				   void __iomem *mmio)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	unsigned long irqflags;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
2318c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe doorbell access", __func__);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	if (db_bits & ~ndev->db_valid_mask)
2348c2ecf20Sopenharmony_ci		return -EINVAL;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ndev->db_mask_lock, irqflags);
2378c2ecf20Sopenharmony_ci	{
2388c2ecf20Sopenharmony_ci		ndev->db_mask |= db_bits;
2398c2ecf20Sopenharmony_ci		ndev->reg->db_iowrite(ndev->db_mask, mmio);
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ndev->db_mask_lock, irqflags);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return 0;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic inline int ndev_db_clear_mask(struct intel_ntb_dev *ndev, u64 db_bits,
2478c2ecf20Sopenharmony_ci				     void __iomem *mmio)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	unsigned long irqflags;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
2528c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe doorbell access", __func__);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (db_bits & ~ndev->db_valid_mask)
2558c2ecf20Sopenharmony_ci		return -EINVAL;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ndev->db_mask_lock, irqflags);
2588c2ecf20Sopenharmony_ci	{
2598c2ecf20Sopenharmony_ci		ndev->db_mask &= ~db_bits;
2608c2ecf20Sopenharmony_ci		ndev->reg->db_iowrite(ndev->db_mask, mmio);
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ndev->db_mask_lock, irqflags);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	return 0;
2658c2ecf20Sopenharmony_ci}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistatic inline u64 ndev_vec_mask(struct intel_ntb_dev *ndev, int db_vector)
2688c2ecf20Sopenharmony_ci{
2698c2ecf20Sopenharmony_ci	u64 shift, mask;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	shift = ndev->db_vec_shift;
2728c2ecf20Sopenharmony_ci	mask = BIT_ULL(shift) - 1;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	return mask << (shift * db_vector);
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic inline int ndev_spad_addr(struct intel_ntb_dev *ndev, int idx,
2788c2ecf20Sopenharmony_ci				 phys_addr_t *spad_addr, phys_addr_t reg_addr,
2798c2ecf20Sopenharmony_ci				 unsigned long reg)
2808c2ecf20Sopenharmony_ci{
2818c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_SPAD))
2828c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe scratchpad access", __func__);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (idx < 0 || idx >= ndev->spad_count)
2858c2ecf20Sopenharmony_ci		return -EINVAL;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (spad_addr) {
2888c2ecf20Sopenharmony_ci		*spad_addr = reg_addr + reg + (idx << 2);
2898c2ecf20Sopenharmony_ci		dev_dbg(&ndev->ntb.pdev->dev, "Peer spad addr %llx\n",
2908c2ecf20Sopenharmony_ci			*spad_addr);
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	return 0;
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic inline u32 ndev_spad_read(struct intel_ntb_dev *ndev, int idx,
2978c2ecf20Sopenharmony_ci				 void __iomem *mmio)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_SPAD))
3008c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe scratchpad access", __func__);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (idx < 0 || idx >= ndev->spad_count)
3038c2ecf20Sopenharmony_ci		return 0;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	return ioread32(mmio + (idx << 2));
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic inline int ndev_spad_write(struct intel_ntb_dev *ndev, int idx, u32 val,
3098c2ecf20Sopenharmony_ci				  void __iomem *mmio)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	if (ndev_is_unsafe(ndev, NTB_UNSAFE_SPAD))
3128c2ecf20Sopenharmony_ci		pr_warn_once("%s: NTB unsafe scratchpad access", __func__);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	if (idx < 0 || idx >= ndev->spad_count)
3158c2ecf20Sopenharmony_ci		return -EINVAL;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	iowrite32(val, mmio + (idx << 2));
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	return 0;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic irqreturn_t ndev_interrupt(struct intel_ntb_dev *ndev, int vec)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	u64 vec_mask;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	vec_mask = ndev_vec_mask(ndev, vec);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if ((ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) && (vec == 31))
3298c2ecf20Sopenharmony_ci		vec_mask |= ndev->db_link_mask;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	dev_dbg(&ndev->ntb.pdev->dev, "vec %d vec_mask %llx\n", vec, vec_mask);
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	ndev->last_ts = jiffies;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	if (vec_mask & ndev->db_link_mask) {
3368c2ecf20Sopenharmony_ci		if (ndev->reg->poll_link(ndev))
3378c2ecf20Sopenharmony_ci			ntb_link_event(&ndev->ntb);
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (vec_mask & ndev->db_valid_mask)
3418c2ecf20Sopenharmony_ci		ntb_db_event(&ndev->ntb, vec);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic irqreturn_t ndev_vec_isr(int irq, void *dev)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	struct intel_ntb_vec *nvec = dev;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	dev_dbg(&nvec->ndev->ntb.pdev->dev, "irq: %d  nvec->num: %d\n",
3518c2ecf20Sopenharmony_ci		irq, nvec->num);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	return ndev_interrupt(nvec->ndev, nvec->num);
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic irqreturn_t ndev_irq_isr(int irq, void *dev)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = dev;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	return ndev_interrupt(ndev, irq - ndev->ntb.pdev->irq);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciint ndev_init_isr(struct intel_ntb_dev *ndev,
3648c2ecf20Sopenharmony_ci			 int msix_min, int msix_max,
3658c2ecf20Sopenharmony_ci			 int msix_shift, int total_shift)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
3688c2ecf20Sopenharmony_ci	int rc, i, msix_count, node;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	pdev = ndev->ntb.pdev;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	node = dev_to_node(&pdev->dev);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	/* Mask all doorbell interrupts */
3758c2ecf20Sopenharmony_ci	ndev->db_mask = ndev->db_valid_mask;
3768c2ecf20Sopenharmony_ci	ndev->reg->db_iowrite(ndev->db_mask,
3778c2ecf20Sopenharmony_ci			      ndev->self_mmio +
3788c2ecf20Sopenharmony_ci			      ndev->self_reg->db_mask);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	/* Try to set up msix irq */
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	ndev->vec = kcalloc_node(msix_max, sizeof(*ndev->vec),
3838c2ecf20Sopenharmony_ci				 GFP_KERNEL, node);
3848c2ecf20Sopenharmony_ci	if (!ndev->vec)
3858c2ecf20Sopenharmony_ci		goto err_msix_vec_alloc;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	ndev->msix = kcalloc_node(msix_max, sizeof(*ndev->msix),
3888c2ecf20Sopenharmony_ci				  GFP_KERNEL, node);
3898c2ecf20Sopenharmony_ci	if (!ndev->msix)
3908c2ecf20Sopenharmony_ci		goto err_msix_alloc;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	for (i = 0; i < msix_max; ++i)
3938c2ecf20Sopenharmony_ci		ndev->msix[i].entry = i;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	msix_count = pci_enable_msix_range(pdev, ndev->msix,
3968c2ecf20Sopenharmony_ci					   msix_min, msix_max);
3978c2ecf20Sopenharmony_ci	if (msix_count < 0)
3988c2ecf20Sopenharmony_ci		goto err_msix_enable;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	for (i = 0; i < msix_count; ++i) {
4018c2ecf20Sopenharmony_ci		ndev->vec[i].ndev = ndev;
4028c2ecf20Sopenharmony_ci		ndev->vec[i].num = i;
4038c2ecf20Sopenharmony_ci		rc = request_irq(ndev->msix[i].vector, ndev_vec_isr, 0,
4048c2ecf20Sopenharmony_ci				 "ndev_vec_isr", &ndev->vec[i]);
4058c2ecf20Sopenharmony_ci		if (rc)
4068c2ecf20Sopenharmony_ci			goto err_msix_request;
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "Using %d msix interrupts\n", msix_count);
4108c2ecf20Sopenharmony_ci	ndev->db_vec_count = msix_count;
4118c2ecf20Sopenharmony_ci	ndev->db_vec_shift = msix_shift;
4128c2ecf20Sopenharmony_ci	return 0;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cierr_msix_request:
4158c2ecf20Sopenharmony_ci	while (i-- > 0)
4168c2ecf20Sopenharmony_ci		free_irq(ndev->msix[i].vector, &ndev->vec[i]);
4178c2ecf20Sopenharmony_ci	pci_disable_msix(pdev);
4188c2ecf20Sopenharmony_cierr_msix_enable:
4198c2ecf20Sopenharmony_ci	kfree(ndev->msix);
4208c2ecf20Sopenharmony_cierr_msix_alloc:
4218c2ecf20Sopenharmony_ci	kfree(ndev->vec);
4228c2ecf20Sopenharmony_cierr_msix_vec_alloc:
4238c2ecf20Sopenharmony_ci	ndev->msix = NULL;
4248c2ecf20Sopenharmony_ci	ndev->vec = NULL;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	/* Try to set up msi irq */
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	rc = pci_enable_msi(pdev);
4298c2ecf20Sopenharmony_ci	if (rc)
4308c2ecf20Sopenharmony_ci		goto err_msi_enable;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	rc = request_irq(pdev->irq, ndev_irq_isr, 0,
4338c2ecf20Sopenharmony_ci			 "ndev_irq_isr", ndev);
4348c2ecf20Sopenharmony_ci	if (rc)
4358c2ecf20Sopenharmony_ci		goto err_msi_request;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "Using msi interrupts\n");
4388c2ecf20Sopenharmony_ci	ndev->db_vec_count = 1;
4398c2ecf20Sopenharmony_ci	ndev->db_vec_shift = total_shift;
4408c2ecf20Sopenharmony_ci	return 0;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_cierr_msi_request:
4438c2ecf20Sopenharmony_ci	pci_disable_msi(pdev);
4448c2ecf20Sopenharmony_cierr_msi_enable:
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	/* Try to set up intx irq */
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	pci_intx(pdev, 1);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	rc = request_irq(pdev->irq, ndev_irq_isr, IRQF_SHARED,
4518c2ecf20Sopenharmony_ci			 "ndev_irq_isr", ndev);
4528c2ecf20Sopenharmony_ci	if (rc)
4538c2ecf20Sopenharmony_ci		goto err_intx_request;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "Using intx interrupts\n");
4568c2ecf20Sopenharmony_ci	ndev->db_vec_count = 1;
4578c2ecf20Sopenharmony_ci	ndev->db_vec_shift = total_shift;
4588c2ecf20Sopenharmony_ci	return 0;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_cierr_intx_request:
4618c2ecf20Sopenharmony_ci	return rc;
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic void ndev_deinit_isr(struct intel_ntb_dev *ndev)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
4678c2ecf20Sopenharmony_ci	int i;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	pdev = ndev->ntb.pdev;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	/* Mask all doorbell interrupts */
4728c2ecf20Sopenharmony_ci	ndev->db_mask = ndev->db_valid_mask;
4738c2ecf20Sopenharmony_ci	ndev->reg->db_iowrite(ndev->db_mask,
4748c2ecf20Sopenharmony_ci			      ndev->self_mmio +
4758c2ecf20Sopenharmony_ci			      ndev->self_reg->db_mask);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	if (ndev->msix) {
4788c2ecf20Sopenharmony_ci		i = ndev->db_vec_count;
4798c2ecf20Sopenharmony_ci		while (i--)
4808c2ecf20Sopenharmony_ci			free_irq(ndev->msix[i].vector, &ndev->vec[i]);
4818c2ecf20Sopenharmony_ci		pci_disable_msix(pdev);
4828c2ecf20Sopenharmony_ci		kfree(ndev->msix);
4838c2ecf20Sopenharmony_ci		kfree(ndev->vec);
4848c2ecf20Sopenharmony_ci	} else {
4858c2ecf20Sopenharmony_ci		free_irq(pdev->irq, ndev);
4868c2ecf20Sopenharmony_ci		if (pci_dev_msi_enabled(pdev))
4878c2ecf20Sopenharmony_ci			pci_disable_msi(pdev);
4888c2ecf20Sopenharmony_ci	}
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic ssize_t ndev_ntb_debugfs_read(struct file *filp, char __user *ubuf,
4928c2ecf20Sopenharmony_ci				     size_t count, loff_t *offp)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev;
4958c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
4968c2ecf20Sopenharmony_ci	void __iomem *mmio;
4978c2ecf20Sopenharmony_ci	char *buf;
4988c2ecf20Sopenharmony_ci	size_t buf_size;
4998c2ecf20Sopenharmony_ci	ssize_t ret, off;
5008c2ecf20Sopenharmony_ci	union { u64 v64; u32 v32; u16 v16; u8 v8; } u;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	ndev = filp->private_data;
5038c2ecf20Sopenharmony_ci	pdev = ndev->ntb.pdev;
5048c2ecf20Sopenharmony_ci	mmio = ndev->self_mmio;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	buf_size = min(count, 0x800ul);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	buf = kmalloc(buf_size, GFP_KERNEL);
5098c2ecf20Sopenharmony_ci	if (!buf)
5108c2ecf20Sopenharmony_ci		return -ENOMEM;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	off = 0;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5158c2ecf20Sopenharmony_ci			 "NTB Device Information:\n");
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5188c2ecf20Sopenharmony_ci			 "Connection Topology -\t%s\n",
5198c2ecf20Sopenharmony_ci			 ntb_topo_string(ndev->ntb.topo));
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	if (ndev->b2b_idx != UINT_MAX) {
5228c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5238c2ecf20Sopenharmony_ci				 "B2B MW Idx -\t\t%u\n", ndev->b2b_idx);
5248c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5258c2ecf20Sopenharmony_ci				 "B2B Offset -\t\t%#lx\n", ndev->b2b_off);
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5298c2ecf20Sopenharmony_ci			 "BAR4 Split -\t\t%s\n",
5308c2ecf20Sopenharmony_ci			 ndev->bar4_split ? "yes" : "no");
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5338c2ecf20Sopenharmony_ci			 "NTB CTL -\t\t%#06x\n", ndev->ntb_ctl);
5348c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5358c2ecf20Sopenharmony_ci			 "LNK STA -\t\t%#06x\n", ndev->lnk_sta);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	if (!ndev->reg->link_is_up(ndev)) {
5388c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5398c2ecf20Sopenharmony_ci				 "Link Status -\t\tDown\n");
5408c2ecf20Sopenharmony_ci	} else {
5418c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5428c2ecf20Sopenharmony_ci				 "Link Status -\t\tUp\n");
5438c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5448c2ecf20Sopenharmony_ci				 "Link Speed -\t\tPCI-E Gen %u\n",
5458c2ecf20Sopenharmony_ci				 NTB_LNK_STA_SPEED(ndev->lnk_sta));
5468c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5478c2ecf20Sopenharmony_ci				 "Link Width -\t\tx%u\n",
5488c2ecf20Sopenharmony_ci				 NTB_LNK_STA_WIDTH(ndev->lnk_sta));
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5528c2ecf20Sopenharmony_ci			 "Memory Window Count -\t%u\n", ndev->mw_count);
5538c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5548c2ecf20Sopenharmony_ci			 "Scratchpad Count -\t%u\n", ndev->spad_count);
5558c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5568c2ecf20Sopenharmony_ci			 "Doorbell Count -\t%u\n", ndev->db_count);
5578c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5588c2ecf20Sopenharmony_ci			 "Doorbell Vector Count -\t%u\n", ndev->db_vec_count);
5598c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5608c2ecf20Sopenharmony_ci			 "Doorbell Vector Shift -\t%u\n", ndev->db_vec_shift);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5638c2ecf20Sopenharmony_ci			 "Doorbell Valid Mask -\t%#llx\n", ndev->db_valid_mask);
5648c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5658c2ecf20Sopenharmony_ci			 "Doorbell Link Mask -\t%#llx\n", ndev->db_link_mask);
5668c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5678c2ecf20Sopenharmony_ci			 "Doorbell Mask Cached -\t%#llx\n", ndev->db_mask);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_mask);
5708c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5718c2ecf20Sopenharmony_ci			 "Doorbell Mask -\t\t%#llx\n", u.v64);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_bell);
5748c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5758c2ecf20Sopenharmony_ci			 "Doorbell Bell -\t\t%#llx\n", u.v64);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5788c2ecf20Sopenharmony_ci			 "\nNTB Window Size:\n");
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	pci_read_config_byte(pdev, XEON_PBAR23SZ_OFFSET, &u.v8);
5818c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5828c2ecf20Sopenharmony_ci			 "PBAR23SZ %hhu\n", u.v8);
5838c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
5848c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_PBAR45SZ_OFFSET, &u.v8);
5858c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5868c2ecf20Sopenharmony_ci				 "PBAR45SZ %hhu\n", u.v8);
5878c2ecf20Sopenharmony_ci	} else {
5888c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_PBAR4SZ_OFFSET, &u.v8);
5898c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5908c2ecf20Sopenharmony_ci				 "PBAR4SZ %hhu\n", u.v8);
5918c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_PBAR5SZ_OFFSET, &u.v8);
5928c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
5938c2ecf20Sopenharmony_ci				 "PBAR5SZ %hhu\n", u.v8);
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	pci_read_config_byte(pdev, XEON_SBAR23SZ_OFFSET, &u.v8);
5978c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
5988c2ecf20Sopenharmony_ci			 "SBAR23SZ %hhu\n", u.v8);
5998c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
6008c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_SBAR45SZ_OFFSET, &u.v8);
6018c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6028c2ecf20Sopenharmony_ci				 "SBAR45SZ %hhu\n", u.v8);
6038c2ecf20Sopenharmony_ci	} else {
6048c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_SBAR4SZ_OFFSET, &u.v8);
6058c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6068c2ecf20Sopenharmony_ci				 "SBAR4SZ %hhu\n", u.v8);
6078c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_SBAR5SZ_OFFSET, &u.v8);
6088c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6098c2ecf20Sopenharmony_ci				 "SBAR5SZ %hhu\n", u.v8);
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
6138c2ecf20Sopenharmony_ci			 "\nNTB Incoming XLAT:\n");
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	u.v64 = ioread64(mmio + bar2_off(ndev->xlat_reg->bar2_xlat, 2));
6168c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
6178c2ecf20Sopenharmony_ci			 "XLAT23 -\t\t%#018llx\n", u.v64);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	if (ndev->bar4_split) {
6208c2ecf20Sopenharmony_ci		u.v32 = ioread32(mmio + bar2_off(ndev->xlat_reg->bar2_xlat, 4));
6218c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6228c2ecf20Sopenharmony_ci				 "XLAT4 -\t\t\t%#06x\n", u.v32);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci		u.v32 = ioread32(mmio + bar2_off(ndev->xlat_reg->bar2_xlat, 5));
6258c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6268c2ecf20Sopenharmony_ci				 "XLAT5 -\t\t\t%#06x\n", u.v32);
6278c2ecf20Sopenharmony_ci	} else {
6288c2ecf20Sopenharmony_ci		u.v64 = ioread64(mmio + bar2_off(ndev->xlat_reg->bar2_xlat, 4));
6298c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6308c2ecf20Sopenharmony_ci				 "XLAT45 -\t\t%#018llx\n", u.v64);
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	u.v64 = ioread64(mmio + bar2_off(ndev->xlat_reg->bar2_limit, 2));
6348c2ecf20Sopenharmony_ci	off += scnprintf(buf + off, buf_size - off,
6358c2ecf20Sopenharmony_ci			 "LMT23 -\t\t\t%#018llx\n", u.v64);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	if (ndev->bar4_split) {
6388c2ecf20Sopenharmony_ci		u.v32 = ioread32(mmio + bar2_off(ndev->xlat_reg->bar2_limit, 4));
6398c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6408c2ecf20Sopenharmony_ci				 "LMT4 -\t\t\t%#06x\n", u.v32);
6418c2ecf20Sopenharmony_ci		u.v32 = ioread32(mmio + bar2_off(ndev->xlat_reg->bar2_limit, 5));
6428c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6438c2ecf20Sopenharmony_ci				 "LMT5 -\t\t\t%#06x\n", u.v32);
6448c2ecf20Sopenharmony_ci	} else {
6458c2ecf20Sopenharmony_ci		u.v64 = ioread64(mmio + bar2_off(ndev->xlat_reg->bar2_limit, 4));
6468c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
6478c2ecf20Sopenharmony_ci				 "LMT45 -\t\t\t%#018llx\n", u.v64);
6488c2ecf20Sopenharmony_ci	}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	if (pdev_is_gen1(pdev)) {
6518c2ecf20Sopenharmony_ci		if (ntb_topo_is_b2b(ndev->ntb.topo)) {
6528c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
6538c2ecf20Sopenharmony_ci					 "\nNTB Outgoing B2B XLAT:\n");
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci			u.v64 = ioread64(mmio + XEON_PBAR23XLAT_OFFSET);
6568c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
6578c2ecf20Sopenharmony_ci					 "B2B XLAT23 -\t\t%#018llx\n", u.v64);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci			if (ndev->bar4_split) {
6608c2ecf20Sopenharmony_ci				u.v32 = ioread32(mmio + XEON_PBAR4XLAT_OFFSET);
6618c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
6628c2ecf20Sopenharmony_ci						 "B2B XLAT4 -\t\t%#06x\n",
6638c2ecf20Sopenharmony_ci						 u.v32);
6648c2ecf20Sopenharmony_ci				u.v32 = ioread32(mmio + XEON_PBAR5XLAT_OFFSET);
6658c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
6668c2ecf20Sopenharmony_ci						 "B2B XLAT5 -\t\t%#06x\n",
6678c2ecf20Sopenharmony_ci						 u.v32);
6688c2ecf20Sopenharmony_ci			} else {
6698c2ecf20Sopenharmony_ci				u.v64 = ioread64(mmio + XEON_PBAR45XLAT_OFFSET);
6708c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
6718c2ecf20Sopenharmony_ci						 "B2B XLAT45 -\t\t%#018llx\n",
6728c2ecf20Sopenharmony_ci						 u.v64);
6738c2ecf20Sopenharmony_ci			}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci			u.v64 = ioread64(mmio + XEON_PBAR23LMT_OFFSET);
6768c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
6778c2ecf20Sopenharmony_ci					 "B2B LMT23 -\t\t%#018llx\n", u.v64);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci			if (ndev->bar4_split) {
6808c2ecf20Sopenharmony_ci				u.v32 = ioread32(mmio + XEON_PBAR4LMT_OFFSET);
6818c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
6828c2ecf20Sopenharmony_ci						 "B2B LMT4 -\t\t%#06x\n",
6838c2ecf20Sopenharmony_ci						 u.v32);
6848c2ecf20Sopenharmony_ci				u.v32 = ioread32(mmio + XEON_PBAR5LMT_OFFSET);
6858c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
6868c2ecf20Sopenharmony_ci						 "B2B LMT5 -\t\t%#06x\n",
6878c2ecf20Sopenharmony_ci						 u.v32);
6888c2ecf20Sopenharmony_ci			} else {
6898c2ecf20Sopenharmony_ci				u.v64 = ioread64(mmio + XEON_PBAR45LMT_OFFSET);
6908c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
6918c2ecf20Sopenharmony_ci						 "B2B LMT45 -\t\t%#018llx\n",
6928c2ecf20Sopenharmony_ci						 u.v64);
6938c2ecf20Sopenharmony_ci			}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
6968c2ecf20Sopenharmony_ci					 "\nNTB Secondary BAR:\n");
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci			u.v64 = ioread64(mmio + XEON_SBAR0BASE_OFFSET);
6998c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
7008c2ecf20Sopenharmony_ci					 "SBAR01 -\t\t%#018llx\n", u.v64);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci			u.v64 = ioread64(mmio + XEON_SBAR23BASE_OFFSET);
7038c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
7048c2ecf20Sopenharmony_ci					 "SBAR23 -\t\t%#018llx\n", u.v64);
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci			if (ndev->bar4_split) {
7078c2ecf20Sopenharmony_ci				u.v32 = ioread32(mmio + XEON_SBAR4BASE_OFFSET);
7088c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
7098c2ecf20Sopenharmony_ci						 "SBAR4 -\t\t\t%#06x\n", u.v32);
7108c2ecf20Sopenharmony_ci				u.v32 = ioread32(mmio + XEON_SBAR5BASE_OFFSET);
7118c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
7128c2ecf20Sopenharmony_ci						 "SBAR5 -\t\t\t%#06x\n", u.v32);
7138c2ecf20Sopenharmony_ci			} else {
7148c2ecf20Sopenharmony_ci				u.v64 = ioread64(mmio + XEON_SBAR45BASE_OFFSET);
7158c2ecf20Sopenharmony_ci				off += scnprintf(buf + off, buf_size - off,
7168c2ecf20Sopenharmony_ci						 "SBAR45 -\t\t%#018llx\n",
7178c2ecf20Sopenharmony_ci						 u.v64);
7188c2ecf20Sopenharmony_ci			}
7198c2ecf20Sopenharmony_ci		}
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
7228c2ecf20Sopenharmony_ci				 "\nXEON NTB Statistics:\n");
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci		u.v16 = ioread16(mmio + XEON_USMEMMISS_OFFSET);
7258c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
7268c2ecf20Sopenharmony_ci				 "Upstream Memory Miss -\t%u\n", u.v16);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci		off += scnprintf(buf + off, buf_size - off,
7298c2ecf20Sopenharmony_ci				 "\nXEON NTB Hardware Errors:\n");
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci		if (!pci_read_config_word(pdev,
7328c2ecf20Sopenharmony_ci					  XEON_DEVSTS_OFFSET, &u.v16))
7338c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
7348c2ecf20Sopenharmony_ci					 "DEVSTS -\t\t%#06x\n", u.v16);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci		if (!pci_read_config_word(pdev,
7378c2ecf20Sopenharmony_ci					  XEON_LINK_STATUS_OFFSET, &u.v16))
7388c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
7398c2ecf20Sopenharmony_ci					 "LNKSTS -\t\t%#06x\n", u.v16);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci		if (!pci_read_config_dword(pdev,
7428c2ecf20Sopenharmony_ci					   XEON_UNCERRSTS_OFFSET, &u.v32))
7438c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
7448c2ecf20Sopenharmony_ci					 "UNCERRSTS -\t\t%#06x\n", u.v32);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci		if (!pci_read_config_dword(pdev,
7478c2ecf20Sopenharmony_ci					   XEON_CORERRSTS_OFFSET, &u.v32))
7488c2ecf20Sopenharmony_ci			off += scnprintf(buf + off, buf_size - off,
7498c2ecf20Sopenharmony_ci					 "CORERRSTS -\t\t%#06x\n", u.v32);
7508c2ecf20Sopenharmony_ci	}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(ubuf, count, offp, buf, off);
7538c2ecf20Sopenharmony_ci	kfree(buf);
7548c2ecf20Sopenharmony_ci	return ret;
7558c2ecf20Sopenharmony_ci}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_cistatic ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
7588c2ecf20Sopenharmony_ci				 size_t count, loff_t *offp)
7598c2ecf20Sopenharmony_ci{
7608c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = filp->private_data;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	if (pdev_is_gen1(ndev->ntb.pdev))
7638c2ecf20Sopenharmony_ci		return ndev_ntb_debugfs_read(filp, ubuf, count, offp);
7648c2ecf20Sopenharmony_ci	else if (pdev_is_gen3(ndev->ntb.pdev))
7658c2ecf20Sopenharmony_ci		return ndev_ntb3_debugfs_read(filp, ubuf, count, offp);
7668c2ecf20Sopenharmony_ci	else if (pdev_is_gen4(ndev->ntb.pdev))
7678c2ecf20Sopenharmony_ci		return ndev_ntb4_debugfs_read(filp, ubuf, count, offp);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	return -ENXIO;
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cistatic void ndev_init_debugfs(struct intel_ntb_dev *ndev)
7738c2ecf20Sopenharmony_ci{
7748c2ecf20Sopenharmony_ci	if (!debugfs_dir) {
7758c2ecf20Sopenharmony_ci		ndev->debugfs_dir = NULL;
7768c2ecf20Sopenharmony_ci		ndev->debugfs_info = NULL;
7778c2ecf20Sopenharmony_ci	} else {
7788c2ecf20Sopenharmony_ci		ndev->debugfs_dir =
7798c2ecf20Sopenharmony_ci			debugfs_create_dir(pci_name(ndev->ntb.pdev),
7808c2ecf20Sopenharmony_ci					   debugfs_dir);
7818c2ecf20Sopenharmony_ci		if (!ndev->debugfs_dir)
7828c2ecf20Sopenharmony_ci			ndev->debugfs_info = NULL;
7838c2ecf20Sopenharmony_ci		else
7848c2ecf20Sopenharmony_ci			ndev->debugfs_info =
7858c2ecf20Sopenharmony_ci				debugfs_create_file("info", S_IRUSR,
7868c2ecf20Sopenharmony_ci						    ndev->debugfs_dir, ndev,
7878c2ecf20Sopenharmony_ci						    &intel_ntb_debugfs_info);
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_cistatic void ndev_deinit_debugfs(struct intel_ntb_dev *ndev)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	debugfs_remove_recursive(ndev->debugfs_dir);
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ciint intel_ntb_mw_count(struct ntb_dev *ntb, int pidx)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	if (pidx != NTB_DEF_PEER_IDX)
7998c2ecf20Sopenharmony_ci		return -EINVAL;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return ntb_ndev(ntb)->mw_count;
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ciint intel_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx,
8058c2ecf20Sopenharmony_ci			   resource_size_t *addr_align,
8068c2ecf20Sopenharmony_ci			   resource_size_t *size_align,
8078c2ecf20Sopenharmony_ci			   resource_size_t *size_max)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
8108c2ecf20Sopenharmony_ci	resource_size_t bar_size, mw_size;
8118c2ecf20Sopenharmony_ci	int bar;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	if (pidx != NTB_DEF_PEER_IDX)
8148c2ecf20Sopenharmony_ci		return -EINVAL;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
8178c2ecf20Sopenharmony_ci		idx += 1;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	bar = ndev_mw_to_bar(ndev, idx);
8208c2ecf20Sopenharmony_ci	if (bar < 0)
8218c2ecf20Sopenharmony_ci		return bar;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	bar_size = pci_resource_len(ndev->ntb.pdev, bar);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	if (idx == ndev->b2b_idx)
8268c2ecf20Sopenharmony_ci		mw_size = bar_size - ndev->b2b_off;
8278c2ecf20Sopenharmony_ci	else
8288c2ecf20Sopenharmony_ci		mw_size = bar_size;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	if (addr_align)
8318c2ecf20Sopenharmony_ci		*addr_align = pci_resource_len(ndev->ntb.pdev, bar);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	if (size_align)
8348c2ecf20Sopenharmony_ci		*size_align = 1;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	if (size_max)
8378c2ecf20Sopenharmony_ci		*size_max = mw_size;
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	return 0;
8408c2ecf20Sopenharmony_ci}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_cistatic int intel_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
8438c2ecf20Sopenharmony_ci				  dma_addr_t addr, resource_size_t size)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
8468c2ecf20Sopenharmony_ci	unsigned long base_reg, xlat_reg, limit_reg;
8478c2ecf20Sopenharmony_ci	resource_size_t bar_size, mw_size;
8488c2ecf20Sopenharmony_ci	void __iomem *mmio;
8498c2ecf20Sopenharmony_ci	u64 base, limit, reg_val;
8508c2ecf20Sopenharmony_ci	int bar;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	if (pidx != NTB_DEF_PEER_IDX)
8538c2ecf20Sopenharmony_ci		return -EINVAL;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
8568c2ecf20Sopenharmony_ci		idx += 1;
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	bar = ndev_mw_to_bar(ndev, idx);
8598c2ecf20Sopenharmony_ci	if (bar < 0)
8608c2ecf20Sopenharmony_ci		return bar;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	bar_size = pci_resource_len(ndev->ntb.pdev, bar);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	if (idx == ndev->b2b_idx)
8658c2ecf20Sopenharmony_ci		mw_size = bar_size - ndev->b2b_off;
8668c2ecf20Sopenharmony_ci	else
8678c2ecf20Sopenharmony_ci		mw_size = bar_size;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	/* hardware requires that addr is aligned to bar size */
8708c2ecf20Sopenharmony_ci	if (addr & (bar_size - 1))
8718c2ecf20Sopenharmony_ci		return -EINVAL;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	/* make sure the range fits in the usable mw size */
8748c2ecf20Sopenharmony_ci	if (size > mw_size)
8758c2ecf20Sopenharmony_ci		return -EINVAL;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	mmio = ndev->self_mmio;
8788c2ecf20Sopenharmony_ci	base_reg = bar0_off(ndev->xlat_reg->bar0_base, bar);
8798c2ecf20Sopenharmony_ci	xlat_reg = bar2_off(ndev->xlat_reg->bar2_xlat, bar);
8808c2ecf20Sopenharmony_ci	limit_reg = bar2_off(ndev->xlat_reg->bar2_limit, bar);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	if (bar < 4 || !ndev->bar4_split) {
8838c2ecf20Sopenharmony_ci		base = ioread64(mmio + base_reg) & NTB_BAR_MASK_64;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci		/* Set the limit if supported, if size is not mw_size */
8868c2ecf20Sopenharmony_ci		if (limit_reg && size != mw_size)
8878c2ecf20Sopenharmony_ci			limit = base + size;
8888c2ecf20Sopenharmony_ci		else
8898c2ecf20Sopenharmony_ci			limit = 0;
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		/* set and verify setting the translation address */
8928c2ecf20Sopenharmony_ci		iowrite64(addr, mmio + xlat_reg);
8938c2ecf20Sopenharmony_ci		reg_val = ioread64(mmio + xlat_reg);
8948c2ecf20Sopenharmony_ci		if (reg_val != addr) {
8958c2ecf20Sopenharmony_ci			iowrite64(0, mmio + xlat_reg);
8968c2ecf20Sopenharmony_ci			return -EIO;
8978c2ecf20Sopenharmony_ci		}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci		/* set and verify setting the limit */
9008c2ecf20Sopenharmony_ci		iowrite64(limit, mmio + limit_reg);
9018c2ecf20Sopenharmony_ci		reg_val = ioread64(mmio + limit_reg);
9028c2ecf20Sopenharmony_ci		if (reg_val != limit) {
9038c2ecf20Sopenharmony_ci			iowrite64(base, mmio + limit_reg);
9048c2ecf20Sopenharmony_ci			iowrite64(0, mmio + xlat_reg);
9058c2ecf20Sopenharmony_ci			return -EIO;
9068c2ecf20Sopenharmony_ci		}
9078c2ecf20Sopenharmony_ci	} else {
9088c2ecf20Sopenharmony_ci		/* split bar addr range must all be 32 bit */
9098c2ecf20Sopenharmony_ci		if (addr & (~0ull << 32))
9108c2ecf20Sopenharmony_ci			return -EINVAL;
9118c2ecf20Sopenharmony_ci		if ((addr + size) & (~0ull << 32))
9128c2ecf20Sopenharmony_ci			return -EINVAL;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci		base = ioread32(mmio + base_reg) & NTB_BAR_MASK_32;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci		/* Set the limit if supported, if size is not mw_size */
9178c2ecf20Sopenharmony_ci		if (limit_reg && size != mw_size)
9188c2ecf20Sopenharmony_ci			limit = base + size;
9198c2ecf20Sopenharmony_ci		else
9208c2ecf20Sopenharmony_ci			limit = 0;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci		/* set and verify setting the translation address */
9238c2ecf20Sopenharmony_ci		iowrite32(addr, mmio + xlat_reg);
9248c2ecf20Sopenharmony_ci		reg_val = ioread32(mmio + xlat_reg);
9258c2ecf20Sopenharmony_ci		if (reg_val != addr) {
9268c2ecf20Sopenharmony_ci			iowrite32(0, mmio + xlat_reg);
9278c2ecf20Sopenharmony_ci			return -EIO;
9288c2ecf20Sopenharmony_ci		}
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci		/* set and verify setting the limit */
9318c2ecf20Sopenharmony_ci		iowrite32(limit, mmio + limit_reg);
9328c2ecf20Sopenharmony_ci		reg_val = ioread32(mmio + limit_reg);
9338c2ecf20Sopenharmony_ci		if (reg_val != limit) {
9348c2ecf20Sopenharmony_ci			iowrite32(base, mmio + limit_reg);
9358c2ecf20Sopenharmony_ci			iowrite32(0, mmio + xlat_reg);
9368c2ecf20Sopenharmony_ci			return -EIO;
9378c2ecf20Sopenharmony_ci		}
9388c2ecf20Sopenharmony_ci	}
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	return 0;
9418c2ecf20Sopenharmony_ci}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ciu64 intel_ntb_link_is_up(struct ntb_dev *ntb, enum ntb_speed *speed,
9448c2ecf20Sopenharmony_ci			 enum ntb_width *width)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	if (ndev->reg->link_is_up(ndev)) {
9498c2ecf20Sopenharmony_ci		if (speed)
9508c2ecf20Sopenharmony_ci			*speed = NTB_LNK_STA_SPEED(ndev->lnk_sta);
9518c2ecf20Sopenharmony_ci		if (width)
9528c2ecf20Sopenharmony_ci			*width = NTB_LNK_STA_WIDTH(ndev->lnk_sta);
9538c2ecf20Sopenharmony_ci		return 1;
9548c2ecf20Sopenharmony_ci	} else {
9558c2ecf20Sopenharmony_ci		/* TODO MAYBE: is it possible to observe the link speed and
9568c2ecf20Sopenharmony_ci		 * width while link is training? */
9578c2ecf20Sopenharmony_ci		if (speed)
9588c2ecf20Sopenharmony_ci			*speed = NTB_SPEED_NONE;
9598c2ecf20Sopenharmony_ci		if (width)
9608c2ecf20Sopenharmony_ci			*width = NTB_WIDTH_NONE;
9618c2ecf20Sopenharmony_ci		return 0;
9628c2ecf20Sopenharmony_ci	}
9638c2ecf20Sopenharmony_ci}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_cistatic int intel_ntb_link_enable(struct ntb_dev *ntb,
9668c2ecf20Sopenharmony_ci				 enum ntb_speed max_speed,
9678c2ecf20Sopenharmony_ci				 enum ntb_width max_width)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev;
9708c2ecf20Sopenharmony_ci	u32 ntb_ctl;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	ndev = container_of(ntb, struct intel_ntb_dev, ntb);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	if (ndev->ntb.topo == NTB_TOPO_SEC)
9758c2ecf20Sopenharmony_ci		return -EINVAL;
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	dev_dbg(&ntb->pdev->dev,
9788c2ecf20Sopenharmony_ci		"Enabling link with max_speed %d max_width %d\n",
9798c2ecf20Sopenharmony_ci		max_speed, max_width);
9808c2ecf20Sopenharmony_ci	if (max_speed != NTB_SPEED_AUTO)
9818c2ecf20Sopenharmony_ci		dev_dbg(&ntb->pdev->dev, "ignoring max_speed %d\n", max_speed);
9828c2ecf20Sopenharmony_ci	if (max_width != NTB_WIDTH_AUTO)
9838c2ecf20Sopenharmony_ci		dev_dbg(&ntb->pdev->dev, "ignoring max_width %d\n", max_width);
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
9868c2ecf20Sopenharmony_ci	ntb_ctl &= ~(NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK);
9878c2ecf20Sopenharmony_ci	ntb_ctl |= NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;
9888c2ecf20Sopenharmony_ci	ntb_ctl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;
9898c2ecf20Sopenharmony_ci	if (ndev->bar4_split)
9908c2ecf20Sopenharmony_ci		ntb_ctl |= NTB_CTL_P2S_BAR5_SNOOP | NTB_CTL_S2P_BAR5_SNOOP;
9918c2ecf20Sopenharmony_ci	iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	return 0;
9948c2ecf20Sopenharmony_ci}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ciint intel_ntb_link_disable(struct ntb_dev *ntb)
9978c2ecf20Sopenharmony_ci{
9988c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev;
9998c2ecf20Sopenharmony_ci	u32 ntb_cntl;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	ndev = container_of(ntb, struct intel_ntb_dev, ntb);
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	if (ndev->ntb.topo == NTB_TOPO_SEC)
10048c2ecf20Sopenharmony_ci		return -EINVAL;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	dev_dbg(&ntb->pdev->dev, "Disabling link\n");
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	/* Bring NTB link down */
10098c2ecf20Sopenharmony_ci	ntb_cntl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
10108c2ecf20Sopenharmony_ci	ntb_cntl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP);
10118c2ecf20Sopenharmony_ci	ntb_cntl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP);
10128c2ecf20Sopenharmony_ci	if (ndev->bar4_split)
10138c2ecf20Sopenharmony_ci		ntb_cntl &= ~(NTB_CTL_P2S_BAR5_SNOOP | NTB_CTL_S2P_BAR5_SNOOP);
10148c2ecf20Sopenharmony_ci	ntb_cntl |= NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK;
10158c2ecf20Sopenharmony_ci	iowrite32(ntb_cntl, ndev->self_mmio + ndev->reg->ntb_ctl);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	return 0;
10188c2ecf20Sopenharmony_ci}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ciint intel_ntb_peer_mw_count(struct ntb_dev *ntb)
10218c2ecf20Sopenharmony_ci{
10228c2ecf20Sopenharmony_ci	/* Numbers of inbound and outbound memory windows match */
10238c2ecf20Sopenharmony_ci	return ntb_ndev(ntb)->mw_count;
10248c2ecf20Sopenharmony_ci}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ciint intel_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
10278c2ecf20Sopenharmony_ci			       phys_addr_t *base, resource_size_t *size)
10288c2ecf20Sopenharmony_ci{
10298c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
10308c2ecf20Sopenharmony_ci	int bar;
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
10338c2ecf20Sopenharmony_ci		idx += 1;
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	bar = ndev_mw_to_bar(ndev, idx);
10368c2ecf20Sopenharmony_ci	if (bar < 0)
10378c2ecf20Sopenharmony_ci		return bar;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	if (base)
10408c2ecf20Sopenharmony_ci		*base = pci_resource_start(ndev->ntb.pdev, bar) +
10418c2ecf20Sopenharmony_ci			(idx == ndev->b2b_idx ? ndev->b2b_off : 0);
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (size)
10448c2ecf20Sopenharmony_ci		*size = pci_resource_len(ndev->ntb.pdev, bar) -
10458c2ecf20Sopenharmony_ci			(idx == ndev->b2b_idx ? ndev->b2b_off : 0);
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	return 0;
10488c2ecf20Sopenharmony_ci}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_cistatic int intel_ntb_db_is_unsafe(struct ntb_dev *ntb)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	return ndev_ignore_unsafe(ntb_ndev(ntb), NTB_UNSAFE_DB);
10538c2ecf20Sopenharmony_ci}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ciu64 intel_ntb_db_valid_mask(struct ntb_dev *ntb)
10568c2ecf20Sopenharmony_ci{
10578c2ecf20Sopenharmony_ci	return ntb_ndev(ntb)->db_valid_mask;
10588c2ecf20Sopenharmony_ci}
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ciint intel_ntb_db_vector_count(struct ntb_dev *ntb)
10618c2ecf20Sopenharmony_ci{
10628c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	ndev = container_of(ntb, struct intel_ntb_dev, ntb);
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	return ndev->db_vec_count;
10678c2ecf20Sopenharmony_ci}
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ciu64 intel_ntb_db_vector_mask(struct ntb_dev *ntb, int db_vector)
10708c2ecf20Sopenharmony_ci{
10718c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	if (db_vector < 0 || db_vector > ndev->db_vec_count)
10748c2ecf20Sopenharmony_ci		return 0;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	return ndev->db_valid_mask & ndev_vec_mask(ndev, db_vector);
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic u64 intel_ntb_db_read(struct ntb_dev *ntb)
10808c2ecf20Sopenharmony_ci{
10818c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	return ndev_db_read(ndev,
10848c2ecf20Sopenharmony_ci			    ndev->self_mmio +
10858c2ecf20Sopenharmony_ci			    ndev->self_reg->db_bell);
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_cistatic int intel_ntb_db_clear(struct ntb_dev *ntb, u64 db_bits)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	return ndev_db_write(ndev, db_bits,
10938c2ecf20Sopenharmony_ci			     ndev->self_mmio +
10948c2ecf20Sopenharmony_ci			     ndev->self_reg->db_bell);
10958c2ecf20Sopenharmony_ci}
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ciint intel_ntb_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	return ndev_db_set_mask(ndev, db_bits,
11028c2ecf20Sopenharmony_ci				ndev->self_mmio +
11038c2ecf20Sopenharmony_ci				ndev->self_reg->db_mask);
11048c2ecf20Sopenharmony_ci}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ciint intel_ntb_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
11078c2ecf20Sopenharmony_ci{
11088c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	return ndev_db_clear_mask(ndev, db_bits,
11118c2ecf20Sopenharmony_ci				  ndev->self_mmio +
11128c2ecf20Sopenharmony_ci				  ndev->self_reg->db_mask);
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic int intel_ntb_peer_db_addr(struct ntb_dev *ntb, phys_addr_t *db_addr,
11168c2ecf20Sopenharmony_ci			   resource_size_t *db_size, u64 *db_data, int db_bit)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	u64 db_bits;
11198c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	if (unlikely(db_bit >= BITS_PER_LONG_LONG))
11228c2ecf20Sopenharmony_ci		return -EINVAL;
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	db_bits = BIT_ULL(db_bit);
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	if (unlikely(db_bits & ~ntb_ndev(ntb)->db_valid_mask))
11278c2ecf20Sopenharmony_ci		return -EINVAL;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	ndev_db_addr(ndev, db_addr, db_size, ndev->peer_addr,
11308c2ecf20Sopenharmony_ci			    ndev->peer_reg->db_bell);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	if (db_data)
11338c2ecf20Sopenharmony_ci		*db_data = db_bits;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	return 0;
11378c2ecf20Sopenharmony_ci}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_cistatic int intel_ntb_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	return ndev_db_write(ndev, db_bits,
11448c2ecf20Sopenharmony_ci			     ndev->peer_mmio +
11458c2ecf20Sopenharmony_ci			     ndev->peer_reg->db_bell);
11468c2ecf20Sopenharmony_ci}
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ciint intel_ntb_spad_is_unsafe(struct ntb_dev *ntb)
11498c2ecf20Sopenharmony_ci{
11508c2ecf20Sopenharmony_ci	return ndev_ignore_unsafe(ntb_ndev(ntb), NTB_UNSAFE_SPAD);
11518c2ecf20Sopenharmony_ci}
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ciint intel_ntb_spad_count(struct ntb_dev *ntb)
11548c2ecf20Sopenharmony_ci{
11558c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	ndev = container_of(ntb, struct intel_ntb_dev, ntb);
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	return ndev->spad_count;
11608c2ecf20Sopenharmony_ci}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ciu32 intel_ntb_spad_read(struct ntb_dev *ntb, int idx)
11638c2ecf20Sopenharmony_ci{
11648c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	return ndev_spad_read(ndev, idx,
11678c2ecf20Sopenharmony_ci			      ndev->self_mmio +
11688c2ecf20Sopenharmony_ci			      ndev->self_reg->spad);
11698c2ecf20Sopenharmony_ci}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ciint intel_ntb_spad_write(struct ntb_dev *ntb, int idx, u32 val)
11728c2ecf20Sopenharmony_ci{
11738c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	return ndev_spad_write(ndev, idx, val,
11768c2ecf20Sopenharmony_ci			       ndev->self_mmio +
11778c2ecf20Sopenharmony_ci			       ndev->self_reg->spad);
11788c2ecf20Sopenharmony_ci}
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ciint intel_ntb_peer_spad_addr(struct ntb_dev *ntb, int pidx, int sidx,
11818c2ecf20Sopenharmony_ci			     phys_addr_t *spad_addr)
11828c2ecf20Sopenharmony_ci{
11838c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	return ndev_spad_addr(ndev, sidx, spad_addr, ndev->peer_addr,
11868c2ecf20Sopenharmony_ci			      ndev->peer_reg->spad);
11878c2ecf20Sopenharmony_ci}
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ciu32 intel_ntb_peer_spad_read(struct ntb_dev *ntb, int pidx, int sidx)
11908c2ecf20Sopenharmony_ci{
11918c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	return ndev_spad_read(ndev, sidx,
11948c2ecf20Sopenharmony_ci			      ndev->peer_mmio +
11958c2ecf20Sopenharmony_ci			      ndev->peer_reg->spad);
11968c2ecf20Sopenharmony_ci}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ciint intel_ntb_peer_spad_write(struct ntb_dev *ntb, int pidx, int sidx,
11998c2ecf20Sopenharmony_ci			      u32 val)
12008c2ecf20Sopenharmony_ci{
12018c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	return ndev_spad_write(ndev, sidx, val,
12048c2ecf20Sopenharmony_ci			       ndev->peer_mmio +
12058c2ecf20Sopenharmony_ci			       ndev->peer_reg->spad);
12068c2ecf20Sopenharmony_ci}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_cistatic u64 xeon_db_ioread(const void __iomem *mmio)
12098c2ecf20Sopenharmony_ci{
12108c2ecf20Sopenharmony_ci	return (u64)ioread16(mmio);
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_cistatic void xeon_db_iowrite(u64 bits, void __iomem *mmio)
12148c2ecf20Sopenharmony_ci{
12158c2ecf20Sopenharmony_ci	iowrite16((u16)bits, mmio);
12168c2ecf20Sopenharmony_ci}
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_cistatic int xeon_poll_link(struct intel_ntb_dev *ndev)
12198c2ecf20Sopenharmony_ci{
12208c2ecf20Sopenharmony_ci	u16 reg_val;
12218c2ecf20Sopenharmony_ci	int rc;
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	ndev->reg->db_iowrite(ndev->db_link_mask,
12248c2ecf20Sopenharmony_ci			      ndev->self_mmio +
12258c2ecf20Sopenharmony_ci			      ndev->self_reg->db_bell);
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	rc = pci_read_config_word(ndev->ntb.pdev,
12288c2ecf20Sopenharmony_ci				  XEON_LINK_STATUS_OFFSET, &reg_val);
12298c2ecf20Sopenharmony_ci	if (rc)
12308c2ecf20Sopenharmony_ci		return 0;
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	if (reg_val == ndev->lnk_sta)
12338c2ecf20Sopenharmony_ci		return 0;
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci	ndev->lnk_sta = reg_val;
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	return 1;
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ciint xeon_link_is_up(struct intel_ntb_dev *ndev)
12418c2ecf20Sopenharmony_ci{
12428c2ecf20Sopenharmony_ci	if (ndev->ntb.topo == NTB_TOPO_SEC)
12438c2ecf20Sopenharmony_ci		return 1;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	return NTB_LNK_STA_ACTIVE(ndev->lnk_sta);
12468c2ecf20Sopenharmony_ci}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_cienum ntb_topo xeon_ppd_topo(struct intel_ntb_dev *ndev, u8 ppd)
12498c2ecf20Sopenharmony_ci{
12508c2ecf20Sopenharmony_ci	switch (ppd & XEON_PPD_TOPO_MASK) {
12518c2ecf20Sopenharmony_ci	case XEON_PPD_TOPO_B2B_USD:
12528c2ecf20Sopenharmony_ci		return NTB_TOPO_B2B_USD;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	case XEON_PPD_TOPO_B2B_DSD:
12558c2ecf20Sopenharmony_ci		return NTB_TOPO_B2B_DSD;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	case XEON_PPD_TOPO_PRI_USD:
12588c2ecf20Sopenharmony_ci	case XEON_PPD_TOPO_PRI_DSD: /* accept bogus PRI_DSD */
12598c2ecf20Sopenharmony_ci		return NTB_TOPO_PRI;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	case XEON_PPD_TOPO_SEC_USD:
12628c2ecf20Sopenharmony_ci	case XEON_PPD_TOPO_SEC_DSD: /* accept bogus SEC_DSD */
12638c2ecf20Sopenharmony_ci		return NTB_TOPO_SEC;
12648c2ecf20Sopenharmony_ci	}
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	return NTB_TOPO_NONE;
12678c2ecf20Sopenharmony_ci}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_cistatic inline int xeon_ppd_bar4_split(struct intel_ntb_dev *ndev, u8 ppd)
12708c2ecf20Sopenharmony_ci{
12718c2ecf20Sopenharmony_ci	if (ppd & XEON_PPD_SPLIT_BAR_MASK) {
12728c2ecf20Sopenharmony_ci		dev_dbg(&ndev->ntb.pdev->dev, "PPD %d split bar\n", ppd);
12738c2ecf20Sopenharmony_ci		return 1;
12748c2ecf20Sopenharmony_ci	}
12758c2ecf20Sopenharmony_ci	return 0;
12768c2ecf20Sopenharmony_ci}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_cistatic int xeon_init_isr(struct intel_ntb_dev *ndev)
12798c2ecf20Sopenharmony_ci{
12808c2ecf20Sopenharmony_ci	return ndev_init_isr(ndev, XEON_DB_MSIX_VECTOR_COUNT,
12818c2ecf20Sopenharmony_ci			     XEON_DB_MSIX_VECTOR_COUNT,
12828c2ecf20Sopenharmony_ci			     XEON_DB_MSIX_VECTOR_SHIFT,
12838c2ecf20Sopenharmony_ci			     XEON_DB_TOTAL_SHIFT);
12848c2ecf20Sopenharmony_ci}
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_cistatic void xeon_deinit_isr(struct intel_ntb_dev *ndev)
12878c2ecf20Sopenharmony_ci{
12888c2ecf20Sopenharmony_ci	ndev_deinit_isr(ndev);
12898c2ecf20Sopenharmony_ci}
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_cistatic int xeon_setup_b2b_mw(struct intel_ntb_dev *ndev,
12928c2ecf20Sopenharmony_ci			     const struct intel_b2b_addr *addr,
12938c2ecf20Sopenharmony_ci			     const struct intel_b2b_addr *peer_addr)
12948c2ecf20Sopenharmony_ci{
12958c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
12968c2ecf20Sopenharmony_ci	void __iomem *mmio;
12978c2ecf20Sopenharmony_ci	resource_size_t bar_size;
12988c2ecf20Sopenharmony_ci	phys_addr_t bar_addr;
12998c2ecf20Sopenharmony_ci	int b2b_bar;
13008c2ecf20Sopenharmony_ci	u8 bar_sz;
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	pdev = ndev->ntb.pdev;
13038c2ecf20Sopenharmony_ci	mmio = ndev->self_mmio;
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	if (ndev->b2b_idx == UINT_MAX) {
13068c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "not using b2b mw\n");
13078c2ecf20Sopenharmony_ci		b2b_bar = 0;
13088c2ecf20Sopenharmony_ci		ndev->b2b_off = 0;
13098c2ecf20Sopenharmony_ci	} else {
13108c2ecf20Sopenharmony_ci		b2b_bar = ndev_mw_to_bar(ndev, ndev->b2b_idx);
13118c2ecf20Sopenharmony_ci		if (b2b_bar < 0)
13128c2ecf20Sopenharmony_ci			return -EIO;
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "using b2b mw bar %d\n", b2b_bar);
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci		bar_size = pci_resource_len(ndev->ntb.pdev, b2b_bar);
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "b2b bar size %#llx\n", bar_size);
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci		if (b2b_mw_share && XEON_B2B_MIN_SIZE <= bar_size >> 1) {
13218c2ecf20Sopenharmony_ci			dev_dbg(&pdev->dev, "b2b using first half of bar\n");
13228c2ecf20Sopenharmony_ci			ndev->b2b_off = bar_size >> 1;
13238c2ecf20Sopenharmony_ci		} else if (XEON_B2B_MIN_SIZE <= bar_size) {
13248c2ecf20Sopenharmony_ci			dev_dbg(&pdev->dev, "b2b using whole bar\n");
13258c2ecf20Sopenharmony_ci			ndev->b2b_off = 0;
13268c2ecf20Sopenharmony_ci			--ndev->mw_count;
13278c2ecf20Sopenharmony_ci		} else {
13288c2ecf20Sopenharmony_ci			dev_dbg(&pdev->dev, "b2b bar size is too small\n");
13298c2ecf20Sopenharmony_ci			return -EIO;
13308c2ecf20Sopenharmony_ci		}
13318c2ecf20Sopenharmony_ci	}
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	/* Reset the secondary bar sizes to match the primary bar sizes,
13348c2ecf20Sopenharmony_ci	 * except disable or halve the size of the b2b secondary bar.
13358c2ecf20Sopenharmony_ci	 *
13368c2ecf20Sopenharmony_ci	 * Note: code for each specific bar size register, because the register
13378c2ecf20Sopenharmony_ci	 * offsets are not in a consistent order (bar5sz comes after ppd, odd).
13388c2ecf20Sopenharmony_ci	 */
13398c2ecf20Sopenharmony_ci	pci_read_config_byte(pdev, XEON_PBAR23SZ_OFFSET, &bar_sz);
13408c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "PBAR23SZ %#x\n", bar_sz);
13418c2ecf20Sopenharmony_ci	if (b2b_bar == 2) {
13428c2ecf20Sopenharmony_ci		if (ndev->b2b_off)
13438c2ecf20Sopenharmony_ci			bar_sz -= 1;
13448c2ecf20Sopenharmony_ci		else
13458c2ecf20Sopenharmony_ci			bar_sz = 0;
13468c2ecf20Sopenharmony_ci	}
13478c2ecf20Sopenharmony_ci	pci_write_config_byte(pdev, XEON_SBAR23SZ_OFFSET, bar_sz);
13488c2ecf20Sopenharmony_ci	pci_read_config_byte(pdev, XEON_SBAR23SZ_OFFSET, &bar_sz);
13498c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "SBAR23SZ %#x\n", bar_sz);
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
13528c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_PBAR45SZ_OFFSET, &bar_sz);
13538c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "PBAR45SZ %#x\n", bar_sz);
13548c2ecf20Sopenharmony_ci		if (b2b_bar == 4) {
13558c2ecf20Sopenharmony_ci			if (ndev->b2b_off)
13568c2ecf20Sopenharmony_ci				bar_sz -= 1;
13578c2ecf20Sopenharmony_ci			else
13588c2ecf20Sopenharmony_ci				bar_sz = 0;
13598c2ecf20Sopenharmony_ci		}
13608c2ecf20Sopenharmony_ci		pci_write_config_byte(pdev, XEON_SBAR45SZ_OFFSET, bar_sz);
13618c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_SBAR45SZ_OFFSET, &bar_sz);
13628c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR45SZ %#x\n", bar_sz);
13638c2ecf20Sopenharmony_ci	} else {
13648c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_PBAR4SZ_OFFSET, &bar_sz);
13658c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "PBAR4SZ %#x\n", bar_sz);
13668c2ecf20Sopenharmony_ci		if (b2b_bar == 4) {
13678c2ecf20Sopenharmony_ci			if (ndev->b2b_off)
13688c2ecf20Sopenharmony_ci				bar_sz -= 1;
13698c2ecf20Sopenharmony_ci			else
13708c2ecf20Sopenharmony_ci				bar_sz = 0;
13718c2ecf20Sopenharmony_ci		}
13728c2ecf20Sopenharmony_ci		pci_write_config_byte(pdev, XEON_SBAR4SZ_OFFSET, bar_sz);
13738c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_SBAR4SZ_OFFSET, &bar_sz);
13748c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR4SZ %#x\n", bar_sz);
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_PBAR5SZ_OFFSET, &bar_sz);
13778c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "PBAR5SZ %#x\n", bar_sz);
13788c2ecf20Sopenharmony_ci		if (b2b_bar == 5) {
13798c2ecf20Sopenharmony_ci			if (ndev->b2b_off)
13808c2ecf20Sopenharmony_ci				bar_sz -= 1;
13818c2ecf20Sopenharmony_ci			else
13828c2ecf20Sopenharmony_ci				bar_sz = 0;
13838c2ecf20Sopenharmony_ci		}
13848c2ecf20Sopenharmony_ci		pci_write_config_byte(pdev, XEON_SBAR5SZ_OFFSET, bar_sz);
13858c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, XEON_SBAR5SZ_OFFSET, &bar_sz);
13868c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR5SZ %#x\n", bar_sz);
13878c2ecf20Sopenharmony_ci	}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	/* SBAR01 hit by first part of the b2b bar */
13908c2ecf20Sopenharmony_ci	if (b2b_bar == 0)
13918c2ecf20Sopenharmony_ci		bar_addr = addr->bar0_addr;
13928c2ecf20Sopenharmony_ci	else if (b2b_bar == 2)
13938c2ecf20Sopenharmony_ci		bar_addr = addr->bar2_addr64;
13948c2ecf20Sopenharmony_ci	else if (b2b_bar == 4 && !ndev->bar4_split)
13958c2ecf20Sopenharmony_ci		bar_addr = addr->bar4_addr64;
13968c2ecf20Sopenharmony_ci	else if (b2b_bar == 4)
13978c2ecf20Sopenharmony_ci		bar_addr = addr->bar4_addr32;
13988c2ecf20Sopenharmony_ci	else if (b2b_bar == 5)
13998c2ecf20Sopenharmony_ci		bar_addr = addr->bar5_addr32;
14008c2ecf20Sopenharmony_ci	else
14018c2ecf20Sopenharmony_ci		return -EIO;
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "SBAR01 %#018llx\n", bar_addr);
14048c2ecf20Sopenharmony_ci	iowrite64(bar_addr, mmio + XEON_SBAR0BASE_OFFSET);
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	/* Other SBAR are normally hit by the PBAR xlat, except for b2b bar.
14078c2ecf20Sopenharmony_ci	 * The b2b bar is either disabled above, or configured half-size, and
14088c2ecf20Sopenharmony_ci	 * it starts at the PBAR xlat + offset.
14098c2ecf20Sopenharmony_ci	 */
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	bar_addr = addr->bar2_addr64 + (b2b_bar == 2 ? ndev->b2b_off : 0);
14128c2ecf20Sopenharmony_ci	iowrite64(bar_addr, mmio + XEON_SBAR23BASE_OFFSET);
14138c2ecf20Sopenharmony_ci	bar_addr = ioread64(mmio + XEON_SBAR23BASE_OFFSET);
14148c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "SBAR23 %#018llx\n", bar_addr);
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
14178c2ecf20Sopenharmony_ci		bar_addr = addr->bar4_addr64 +
14188c2ecf20Sopenharmony_ci			(b2b_bar == 4 ? ndev->b2b_off : 0);
14198c2ecf20Sopenharmony_ci		iowrite64(bar_addr, mmio + XEON_SBAR45BASE_OFFSET);
14208c2ecf20Sopenharmony_ci		bar_addr = ioread64(mmio + XEON_SBAR45BASE_OFFSET);
14218c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR45 %#018llx\n", bar_addr);
14228c2ecf20Sopenharmony_ci	} else {
14238c2ecf20Sopenharmony_ci		bar_addr = addr->bar4_addr32 +
14248c2ecf20Sopenharmony_ci			(b2b_bar == 4 ? ndev->b2b_off : 0);
14258c2ecf20Sopenharmony_ci		iowrite32(bar_addr, mmio + XEON_SBAR4BASE_OFFSET);
14268c2ecf20Sopenharmony_ci		bar_addr = ioread32(mmio + XEON_SBAR4BASE_OFFSET);
14278c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR4 %#010llx\n", bar_addr);
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci		bar_addr = addr->bar5_addr32 +
14308c2ecf20Sopenharmony_ci			(b2b_bar == 5 ? ndev->b2b_off : 0);
14318c2ecf20Sopenharmony_ci		iowrite32(bar_addr, mmio + XEON_SBAR5BASE_OFFSET);
14328c2ecf20Sopenharmony_ci		bar_addr = ioread32(mmio + XEON_SBAR5BASE_OFFSET);
14338c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR5 %#010llx\n", bar_addr);
14348c2ecf20Sopenharmony_ci	}
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	/* setup incoming bar limits == base addrs (zero length windows) */
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	bar_addr = addr->bar2_addr64 + (b2b_bar == 2 ? ndev->b2b_off : 0);
14398c2ecf20Sopenharmony_ci	iowrite64(bar_addr, mmio + XEON_SBAR23LMT_OFFSET);
14408c2ecf20Sopenharmony_ci	bar_addr = ioread64(mmio + XEON_SBAR23LMT_OFFSET);
14418c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "SBAR23LMT %#018llx\n", bar_addr);
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
14448c2ecf20Sopenharmony_ci		bar_addr = addr->bar4_addr64 +
14458c2ecf20Sopenharmony_ci			(b2b_bar == 4 ? ndev->b2b_off : 0);
14468c2ecf20Sopenharmony_ci		iowrite64(bar_addr, mmio + XEON_SBAR45LMT_OFFSET);
14478c2ecf20Sopenharmony_ci		bar_addr = ioread64(mmio + XEON_SBAR45LMT_OFFSET);
14488c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR45LMT %#018llx\n", bar_addr);
14498c2ecf20Sopenharmony_ci	} else {
14508c2ecf20Sopenharmony_ci		bar_addr = addr->bar4_addr32 +
14518c2ecf20Sopenharmony_ci			(b2b_bar == 4 ? ndev->b2b_off : 0);
14528c2ecf20Sopenharmony_ci		iowrite32(bar_addr, mmio + XEON_SBAR4LMT_OFFSET);
14538c2ecf20Sopenharmony_ci		bar_addr = ioread32(mmio + XEON_SBAR4LMT_OFFSET);
14548c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR4LMT %#010llx\n", bar_addr);
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci		bar_addr = addr->bar5_addr32 +
14578c2ecf20Sopenharmony_ci			(b2b_bar == 5 ? ndev->b2b_off : 0);
14588c2ecf20Sopenharmony_ci		iowrite32(bar_addr, mmio + XEON_SBAR5LMT_OFFSET);
14598c2ecf20Sopenharmony_ci		bar_addr = ioread32(mmio + XEON_SBAR5LMT_OFFSET);
14608c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "SBAR5LMT %#05llx\n", bar_addr);
14618c2ecf20Sopenharmony_ci	}
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	/* zero incoming translation addrs */
14648c2ecf20Sopenharmony_ci	iowrite64(0, mmio + XEON_SBAR23XLAT_OFFSET);
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
14678c2ecf20Sopenharmony_ci		iowrite64(0, mmio + XEON_SBAR45XLAT_OFFSET);
14688c2ecf20Sopenharmony_ci	} else {
14698c2ecf20Sopenharmony_ci		iowrite32(0, mmio + XEON_SBAR4XLAT_OFFSET);
14708c2ecf20Sopenharmony_ci		iowrite32(0, mmio + XEON_SBAR5XLAT_OFFSET);
14718c2ecf20Sopenharmony_ci	}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	/* zero outgoing translation limits (whole bar size windows) */
14748c2ecf20Sopenharmony_ci	iowrite64(0, mmio + XEON_PBAR23LMT_OFFSET);
14758c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
14768c2ecf20Sopenharmony_ci		iowrite64(0, mmio + XEON_PBAR45LMT_OFFSET);
14778c2ecf20Sopenharmony_ci	} else {
14788c2ecf20Sopenharmony_ci		iowrite32(0, mmio + XEON_PBAR4LMT_OFFSET);
14798c2ecf20Sopenharmony_ci		iowrite32(0, mmio + XEON_PBAR5LMT_OFFSET);
14808c2ecf20Sopenharmony_ci	}
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	/* set outgoing translation offsets */
14838c2ecf20Sopenharmony_ci	bar_addr = peer_addr->bar2_addr64;
14848c2ecf20Sopenharmony_ci	iowrite64(bar_addr, mmio + XEON_PBAR23XLAT_OFFSET);
14858c2ecf20Sopenharmony_ci	bar_addr = ioread64(mmio + XEON_PBAR23XLAT_OFFSET);
14868c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "PBAR23XLAT %#018llx\n", bar_addr);
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	if (!ndev->bar4_split) {
14898c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar4_addr64;
14908c2ecf20Sopenharmony_ci		iowrite64(bar_addr, mmio + XEON_PBAR45XLAT_OFFSET);
14918c2ecf20Sopenharmony_ci		bar_addr = ioread64(mmio + XEON_PBAR45XLAT_OFFSET);
14928c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "PBAR45XLAT %#018llx\n", bar_addr);
14938c2ecf20Sopenharmony_ci	} else {
14948c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar4_addr32;
14958c2ecf20Sopenharmony_ci		iowrite32(bar_addr, mmio + XEON_PBAR4XLAT_OFFSET);
14968c2ecf20Sopenharmony_ci		bar_addr = ioread32(mmio + XEON_PBAR4XLAT_OFFSET);
14978c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "PBAR4XLAT %#010llx\n", bar_addr);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar5_addr32;
15008c2ecf20Sopenharmony_ci		iowrite32(bar_addr, mmio + XEON_PBAR5XLAT_OFFSET);
15018c2ecf20Sopenharmony_ci		bar_addr = ioread32(mmio + XEON_PBAR5XLAT_OFFSET);
15028c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "PBAR5XLAT %#010llx\n", bar_addr);
15038c2ecf20Sopenharmony_ci	}
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci	/* set the translation offset for b2b registers */
15068c2ecf20Sopenharmony_ci	if (b2b_bar == 0)
15078c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar0_addr;
15088c2ecf20Sopenharmony_ci	else if (b2b_bar == 2)
15098c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar2_addr64;
15108c2ecf20Sopenharmony_ci	else if (b2b_bar == 4 && !ndev->bar4_split)
15118c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar4_addr64;
15128c2ecf20Sopenharmony_ci	else if (b2b_bar == 4)
15138c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar4_addr32;
15148c2ecf20Sopenharmony_ci	else if (b2b_bar == 5)
15158c2ecf20Sopenharmony_ci		bar_addr = peer_addr->bar5_addr32;
15168c2ecf20Sopenharmony_ci	else
15178c2ecf20Sopenharmony_ci		return -EIO;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	/* B2B_XLAT_OFFSET is 64bit, but can only take 32bit writes */
15208c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "B2BXLAT %#018llx\n", bar_addr);
15218c2ecf20Sopenharmony_ci	iowrite32(bar_addr, mmio + XEON_B2B_XLAT_OFFSETL);
15228c2ecf20Sopenharmony_ci	iowrite32(bar_addr >> 32, mmio + XEON_B2B_XLAT_OFFSETU);
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	if (b2b_bar) {
15258c2ecf20Sopenharmony_ci		/* map peer ntb mmio config space registers */
15268c2ecf20Sopenharmony_ci		ndev->peer_mmio = pci_iomap(pdev, b2b_bar,
15278c2ecf20Sopenharmony_ci					    XEON_B2B_MIN_SIZE);
15288c2ecf20Sopenharmony_ci		if (!ndev->peer_mmio)
15298c2ecf20Sopenharmony_ci			return -EIO;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci		ndev->peer_addr = pci_resource_start(pdev, b2b_bar);
15328c2ecf20Sopenharmony_ci	}
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	return 0;
15358c2ecf20Sopenharmony_ci}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_cistatic int xeon_init_ntb(struct intel_ntb_dev *ndev)
15388c2ecf20Sopenharmony_ci{
15398c2ecf20Sopenharmony_ci	struct device *dev = &ndev->ntb.pdev->dev;
15408c2ecf20Sopenharmony_ci	int rc;
15418c2ecf20Sopenharmony_ci	u32 ntb_ctl;
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	if (ndev->bar4_split)
15448c2ecf20Sopenharmony_ci		ndev->mw_count = HSX_SPLIT_BAR_MW_COUNT;
15458c2ecf20Sopenharmony_ci	else
15468c2ecf20Sopenharmony_ci		ndev->mw_count = XEON_MW_COUNT;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	ndev->spad_count = XEON_SPAD_COUNT;
15498c2ecf20Sopenharmony_ci	ndev->db_count = XEON_DB_COUNT;
15508c2ecf20Sopenharmony_ci	ndev->db_link_mask = XEON_DB_LINK_BIT;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	switch (ndev->ntb.topo) {
15538c2ecf20Sopenharmony_ci	case NTB_TOPO_PRI:
15548c2ecf20Sopenharmony_ci		if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP) {
15558c2ecf20Sopenharmony_ci			dev_err(dev, "NTB Primary config disabled\n");
15568c2ecf20Sopenharmony_ci			return -EINVAL;
15578c2ecf20Sopenharmony_ci		}
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci		/* enable link to allow secondary side device to appear */
15608c2ecf20Sopenharmony_ci		ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
15618c2ecf20Sopenharmony_ci		ntb_ctl &= ~NTB_CTL_DISABLE;
15628c2ecf20Sopenharmony_ci		iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci		/* use half the spads for the peer */
15658c2ecf20Sopenharmony_ci		ndev->spad_count >>= 1;
15668c2ecf20Sopenharmony_ci		ndev->self_reg = &xeon_pri_reg;
15678c2ecf20Sopenharmony_ci		ndev->peer_reg = &xeon_sec_reg;
15688c2ecf20Sopenharmony_ci		ndev->xlat_reg = &xeon_sec_xlat;
15698c2ecf20Sopenharmony_ci		break;
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	case NTB_TOPO_SEC:
15728c2ecf20Sopenharmony_ci		if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP) {
15738c2ecf20Sopenharmony_ci			dev_err(dev, "NTB Secondary config disabled\n");
15748c2ecf20Sopenharmony_ci			return -EINVAL;
15758c2ecf20Sopenharmony_ci		}
15768c2ecf20Sopenharmony_ci		/* use half the spads for the peer */
15778c2ecf20Sopenharmony_ci		ndev->spad_count >>= 1;
15788c2ecf20Sopenharmony_ci		ndev->self_reg = &xeon_sec_reg;
15798c2ecf20Sopenharmony_ci		ndev->peer_reg = &xeon_pri_reg;
15808c2ecf20Sopenharmony_ci		ndev->xlat_reg = &xeon_pri_xlat;
15818c2ecf20Sopenharmony_ci		break;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	case NTB_TOPO_B2B_USD:
15848c2ecf20Sopenharmony_ci	case NTB_TOPO_B2B_DSD:
15858c2ecf20Sopenharmony_ci		ndev->self_reg = &xeon_pri_reg;
15868c2ecf20Sopenharmony_ci		ndev->peer_reg = &xeon_b2b_reg;
15878c2ecf20Sopenharmony_ci		ndev->xlat_reg = &xeon_sec_xlat;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci		if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP) {
15908c2ecf20Sopenharmony_ci			ndev->peer_reg = &xeon_pri_reg;
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci			if (b2b_mw_idx < 0)
15938c2ecf20Sopenharmony_ci				ndev->b2b_idx = b2b_mw_idx + ndev->mw_count;
15948c2ecf20Sopenharmony_ci			else
15958c2ecf20Sopenharmony_ci				ndev->b2b_idx = b2b_mw_idx;
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci			if (ndev->b2b_idx >= ndev->mw_count) {
15988c2ecf20Sopenharmony_ci				dev_dbg(dev,
15998c2ecf20Sopenharmony_ci					"b2b_mw_idx %d invalid for mw_count %u\n",
16008c2ecf20Sopenharmony_ci					b2b_mw_idx, ndev->mw_count);
16018c2ecf20Sopenharmony_ci				return -EINVAL;
16028c2ecf20Sopenharmony_ci			}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci			dev_dbg(dev, "setting up b2b mw idx %d means %d\n",
16058c2ecf20Sopenharmony_ci				b2b_mw_idx, ndev->b2b_idx);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci		} else if (ndev->hwerr_flags & NTB_HWERR_B2BDOORBELL_BIT14) {
16088c2ecf20Sopenharmony_ci			dev_warn(dev, "Reduce doorbell count by 1\n");
16098c2ecf20Sopenharmony_ci			ndev->db_count -= 1;
16108c2ecf20Sopenharmony_ci		}
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci		if (ndev->ntb.topo == NTB_TOPO_B2B_USD) {
16138c2ecf20Sopenharmony_ci			rc = xeon_setup_b2b_mw(ndev,
16148c2ecf20Sopenharmony_ci					       &xeon_b2b_dsd_addr,
16158c2ecf20Sopenharmony_ci					       &xeon_b2b_usd_addr);
16168c2ecf20Sopenharmony_ci		} else {
16178c2ecf20Sopenharmony_ci			rc = xeon_setup_b2b_mw(ndev,
16188c2ecf20Sopenharmony_ci					       &xeon_b2b_usd_addr,
16198c2ecf20Sopenharmony_ci					       &xeon_b2b_dsd_addr);
16208c2ecf20Sopenharmony_ci		}
16218c2ecf20Sopenharmony_ci		if (rc)
16228c2ecf20Sopenharmony_ci			return rc;
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci		/* Enable Bus Master and Memory Space on the secondary side */
16258c2ecf20Sopenharmony_ci		iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
16268c2ecf20Sopenharmony_ci			  ndev->self_mmio + XEON_SPCICMD_OFFSET);
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci		break;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	default:
16318c2ecf20Sopenharmony_ci		return -EINVAL;
16328c2ecf20Sopenharmony_ci	}
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci	ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	ndev->reg->db_iowrite(ndev->db_valid_mask,
16378c2ecf20Sopenharmony_ci			      ndev->self_mmio +
16388c2ecf20Sopenharmony_ci			      ndev->self_reg->db_mask);
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_ci	return 0;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_cistatic int xeon_init_dev(struct intel_ntb_dev *ndev)
16448c2ecf20Sopenharmony_ci{
16458c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
16468c2ecf20Sopenharmony_ci	u8 ppd;
16478c2ecf20Sopenharmony_ci	int rc, mem;
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	pdev = ndev->ntb.pdev;
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	switch (pdev->device) {
16528c2ecf20Sopenharmony_ci	/* There is a Xeon hardware errata related to writes to SDOORBELL or
16538c2ecf20Sopenharmony_ci	 * B2BDOORBELL in conjunction with inbound access to NTB MMIO Space,
16548c2ecf20Sopenharmony_ci	 * which may hang the system.  To workaround this use the second memory
16558c2ecf20Sopenharmony_ci	 * window to access the interrupt and scratch pad registers on the
16568c2ecf20Sopenharmony_ci	 * remote system.
16578c2ecf20Sopenharmony_ci	 */
16588c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_JSF:
16598c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_JSF:
16608c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF:
16618c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_SNB:
16628c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_SNB:
16638c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB:
16648c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_IVT:
16658c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_IVT:
16668c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT:
16678c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
16688c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
16698c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
16708c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
16718c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
16728c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
16738c2ecf20Sopenharmony_ci		ndev->hwerr_flags |= NTB_HWERR_SDOORBELL_LOCKUP;
16748c2ecf20Sopenharmony_ci		break;
16758c2ecf20Sopenharmony_ci	}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	switch (pdev->device) {
16788c2ecf20Sopenharmony_ci	/* There is a hardware errata related to accessing any register in
16798c2ecf20Sopenharmony_ci	 * SB01BASE in the presence of bidirectional traffic crossing the NTB.
16808c2ecf20Sopenharmony_ci	 */
16818c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_IVT:
16828c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_IVT:
16838c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT:
16848c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
16858c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
16868c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
16878c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
16888c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
16898c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
16908c2ecf20Sopenharmony_ci		ndev->hwerr_flags |= NTB_HWERR_SB01BASE_LOCKUP;
16918c2ecf20Sopenharmony_ci		break;
16928c2ecf20Sopenharmony_ci	}
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	switch (pdev->device) {
16958c2ecf20Sopenharmony_ci	/* HW Errata on bit 14 of b2bdoorbell register.  Writes will not be
16968c2ecf20Sopenharmony_ci	 * mirrored to the remote system.  Shrink the number of bits by one,
16978c2ecf20Sopenharmony_ci	 * since bit 14 is the last bit.
16988c2ecf20Sopenharmony_ci	 */
16998c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_JSF:
17008c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_JSF:
17018c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF:
17028c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_SNB:
17038c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_SNB:
17048c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB:
17058c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_IVT:
17068c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_IVT:
17078c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT:
17088c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
17098c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
17108c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
17118c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
17128c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
17138c2ecf20Sopenharmony_ci	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
17148c2ecf20Sopenharmony_ci		ndev->hwerr_flags |= NTB_HWERR_B2BDOORBELL_BIT14;
17158c2ecf20Sopenharmony_ci		break;
17168c2ecf20Sopenharmony_ci	}
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	ndev->reg = &xeon_reg;
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci	rc = pci_read_config_byte(pdev, XEON_PPD_OFFSET, &ppd);
17218c2ecf20Sopenharmony_ci	if (rc)
17228c2ecf20Sopenharmony_ci		return -EIO;
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	ndev->ntb.topo = xeon_ppd_topo(ndev, ppd);
17258c2ecf20Sopenharmony_ci	dev_dbg(&pdev->dev, "ppd %#x topo %s\n", ppd,
17268c2ecf20Sopenharmony_ci		ntb_topo_string(ndev->ntb.topo));
17278c2ecf20Sopenharmony_ci	if (ndev->ntb.topo == NTB_TOPO_NONE)
17288c2ecf20Sopenharmony_ci		return -EINVAL;
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	if (ndev->ntb.topo != NTB_TOPO_SEC) {
17318c2ecf20Sopenharmony_ci		ndev->bar4_split = xeon_ppd_bar4_split(ndev, ppd);
17328c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "ppd %#x bar4_split %d\n",
17338c2ecf20Sopenharmony_ci			ppd, ndev->bar4_split);
17348c2ecf20Sopenharmony_ci	} else {
17358c2ecf20Sopenharmony_ci		/* This is a way for transparent BAR to figure out if we are
17368c2ecf20Sopenharmony_ci		 * doing split BAR or not. There is no way for the hw on the
17378c2ecf20Sopenharmony_ci		 * transparent side to know and set the PPD.
17388c2ecf20Sopenharmony_ci		 */
17398c2ecf20Sopenharmony_ci		mem = pci_select_bars(pdev, IORESOURCE_MEM);
17408c2ecf20Sopenharmony_ci		ndev->bar4_split = hweight32(mem) ==
17418c2ecf20Sopenharmony_ci			HSX_SPLIT_BAR_MW_COUNT + 1;
17428c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "mem %#x bar4_split %d\n",
17438c2ecf20Sopenharmony_ci			mem, ndev->bar4_split);
17448c2ecf20Sopenharmony_ci	}
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci	rc = xeon_init_ntb(ndev);
17478c2ecf20Sopenharmony_ci	if (rc)
17488c2ecf20Sopenharmony_ci		return rc;
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci	return xeon_init_isr(ndev);
17518c2ecf20Sopenharmony_ci}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_cistatic void xeon_deinit_dev(struct intel_ntb_dev *ndev)
17548c2ecf20Sopenharmony_ci{
17558c2ecf20Sopenharmony_ci	xeon_deinit_isr(ndev);
17568c2ecf20Sopenharmony_ci}
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_cistatic int intel_ntb_init_pci(struct intel_ntb_dev *ndev, struct pci_dev *pdev)
17598c2ecf20Sopenharmony_ci{
17608c2ecf20Sopenharmony_ci	int rc;
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, ndev);
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	rc = pci_enable_device(pdev);
17658c2ecf20Sopenharmony_ci	if (rc)
17668c2ecf20Sopenharmony_ci		goto err_pci_enable;
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	rc = pci_request_regions(pdev, NTB_NAME);
17698c2ecf20Sopenharmony_ci	if (rc)
17708c2ecf20Sopenharmony_ci		goto err_pci_regions;
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	pci_set_master(pdev);
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
17758c2ecf20Sopenharmony_ci	if (rc) {
17768c2ecf20Sopenharmony_ci		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
17778c2ecf20Sopenharmony_ci		if (rc)
17788c2ecf20Sopenharmony_ci			goto err_dma_mask;
17798c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "Cannot DMA highmem\n");
17808c2ecf20Sopenharmony_ci	}
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
17838c2ecf20Sopenharmony_ci	if (rc) {
17848c2ecf20Sopenharmony_ci		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
17858c2ecf20Sopenharmony_ci		if (rc)
17868c2ecf20Sopenharmony_ci			goto err_dma_mask;
17878c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "Cannot DMA consistent highmem\n");
17888c2ecf20Sopenharmony_ci	}
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	ndev->self_mmio = pci_iomap(pdev, 0, 0);
17918c2ecf20Sopenharmony_ci	if (!ndev->self_mmio) {
17928c2ecf20Sopenharmony_ci		rc = -EIO;
17938c2ecf20Sopenharmony_ci		goto err_mmio;
17948c2ecf20Sopenharmony_ci	}
17958c2ecf20Sopenharmony_ci	ndev->peer_mmio = ndev->self_mmio;
17968c2ecf20Sopenharmony_ci	ndev->peer_addr = pci_resource_start(pdev, 0);
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	return 0;
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_cierr_mmio:
18018c2ecf20Sopenharmony_cierr_dma_mask:
18028c2ecf20Sopenharmony_ci	pci_clear_master(pdev);
18038c2ecf20Sopenharmony_ci	pci_release_regions(pdev);
18048c2ecf20Sopenharmony_cierr_pci_regions:
18058c2ecf20Sopenharmony_ci	pci_disable_device(pdev);
18068c2ecf20Sopenharmony_cierr_pci_enable:
18078c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
18088c2ecf20Sopenharmony_ci	return rc;
18098c2ecf20Sopenharmony_ci}
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_cistatic void intel_ntb_deinit_pci(struct intel_ntb_dev *ndev)
18128c2ecf20Sopenharmony_ci{
18138c2ecf20Sopenharmony_ci	struct pci_dev *pdev = ndev->ntb.pdev;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	if (ndev->peer_mmio && ndev->peer_mmio != ndev->self_mmio)
18168c2ecf20Sopenharmony_ci		pci_iounmap(pdev, ndev->peer_mmio);
18178c2ecf20Sopenharmony_ci	pci_iounmap(pdev, ndev->self_mmio);
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	pci_clear_master(pdev);
18208c2ecf20Sopenharmony_ci	pci_release_regions(pdev);
18218c2ecf20Sopenharmony_ci	pci_disable_device(pdev);
18228c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
18238c2ecf20Sopenharmony_ci}
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_cistatic inline void ndev_init_struct(struct intel_ntb_dev *ndev,
18268c2ecf20Sopenharmony_ci				    struct pci_dev *pdev)
18278c2ecf20Sopenharmony_ci{
18288c2ecf20Sopenharmony_ci	ndev->ntb.pdev = pdev;
18298c2ecf20Sopenharmony_ci	ndev->ntb.topo = NTB_TOPO_NONE;
18308c2ecf20Sopenharmony_ci	ndev->ntb.ops = &intel_ntb_ops;
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	ndev->b2b_off = 0;
18338c2ecf20Sopenharmony_ci	ndev->b2b_idx = UINT_MAX;
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	ndev->bar4_split = 0;
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci	ndev->mw_count = 0;
18388c2ecf20Sopenharmony_ci	ndev->spad_count = 0;
18398c2ecf20Sopenharmony_ci	ndev->db_count = 0;
18408c2ecf20Sopenharmony_ci	ndev->db_vec_count = 0;
18418c2ecf20Sopenharmony_ci	ndev->db_vec_shift = 0;
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	ndev->ntb_ctl = 0;
18448c2ecf20Sopenharmony_ci	ndev->lnk_sta = 0;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci	ndev->db_valid_mask = 0;
18478c2ecf20Sopenharmony_ci	ndev->db_link_mask = 0;
18488c2ecf20Sopenharmony_ci	ndev->db_mask = 0;
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	spin_lock_init(&ndev->db_mask_lock);
18518c2ecf20Sopenharmony_ci}
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_cistatic int intel_ntb_pci_probe(struct pci_dev *pdev,
18548c2ecf20Sopenharmony_ci			       const struct pci_device_id *id)
18558c2ecf20Sopenharmony_ci{
18568c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev;
18578c2ecf20Sopenharmony_ci	int rc, node;
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci	node = dev_to_node(&pdev->dev);
18608c2ecf20Sopenharmony_ci	ndev = kzalloc_node(sizeof(*ndev), GFP_KERNEL, node);
18618c2ecf20Sopenharmony_ci	if (!ndev) {
18628c2ecf20Sopenharmony_ci		rc = -ENOMEM;
18638c2ecf20Sopenharmony_ci		goto err_ndev;
18648c2ecf20Sopenharmony_ci	}
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	ndev_init_struct(ndev, pdev);
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	if (pdev_is_gen1(pdev)) {
18698c2ecf20Sopenharmony_ci		rc = intel_ntb_init_pci(ndev, pdev);
18708c2ecf20Sopenharmony_ci		if (rc)
18718c2ecf20Sopenharmony_ci			goto err_init_pci;
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci		rc = xeon_init_dev(ndev);
18748c2ecf20Sopenharmony_ci		if (rc)
18758c2ecf20Sopenharmony_ci			goto err_init_dev;
18768c2ecf20Sopenharmony_ci	} else if (pdev_is_gen3(pdev)) {
18778c2ecf20Sopenharmony_ci		ndev->ntb.ops = &intel_ntb3_ops;
18788c2ecf20Sopenharmony_ci		rc = intel_ntb_init_pci(ndev, pdev);
18798c2ecf20Sopenharmony_ci		if (rc)
18808c2ecf20Sopenharmony_ci			goto err_init_pci;
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci		rc = gen3_init_dev(ndev);
18838c2ecf20Sopenharmony_ci		if (rc)
18848c2ecf20Sopenharmony_ci			goto err_init_dev;
18858c2ecf20Sopenharmony_ci	} else if (pdev_is_gen4(pdev)) {
18868c2ecf20Sopenharmony_ci		ndev->ntb.ops = &intel_ntb4_ops;
18878c2ecf20Sopenharmony_ci		rc = intel_ntb_init_pci(ndev, pdev);
18888c2ecf20Sopenharmony_ci		if (rc)
18898c2ecf20Sopenharmony_ci			goto err_init_pci;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci		rc = gen4_init_dev(ndev);
18928c2ecf20Sopenharmony_ci		if (rc)
18938c2ecf20Sopenharmony_ci			goto err_init_dev;
18948c2ecf20Sopenharmony_ci	} else {
18958c2ecf20Sopenharmony_ci		rc = -EINVAL;
18968c2ecf20Sopenharmony_ci		goto err_init_pci;
18978c2ecf20Sopenharmony_ci	}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	ndev_reset_unsafe_flags(ndev);
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	ndev->reg->poll_link(ndev);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	ndev_init_debugfs(ndev);
19048c2ecf20Sopenharmony_ci
19058c2ecf20Sopenharmony_ci	rc = ntb_register_device(&ndev->ntb);
19068c2ecf20Sopenharmony_ci	if (rc)
19078c2ecf20Sopenharmony_ci		goto err_register;
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "NTB device registered.\n");
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	return 0;
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_cierr_register:
19148c2ecf20Sopenharmony_ci	ndev_deinit_debugfs(ndev);
19158c2ecf20Sopenharmony_ci	if (pdev_is_gen1(pdev) || pdev_is_gen3(pdev) || pdev_is_gen4(pdev))
19168c2ecf20Sopenharmony_ci		xeon_deinit_dev(ndev);
19178c2ecf20Sopenharmony_cierr_init_dev:
19188c2ecf20Sopenharmony_ci	intel_ntb_deinit_pci(ndev);
19198c2ecf20Sopenharmony_cierr_init_pci:
19208c2ecf20Sopenharmony_ci	kfree(ndev);
19218c2ecf20Sopenharmony_cierr_ndev:
19228c2ecf20Sopenharmony_ci	return rc;
19238c2ecf20Sopenharmony_ci}
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_cistatic void intel_ntb_pci_remove(struct pci_dev *pdev)
19268c2ecf20Sopenharmony_ci{
19278c2ecf20Sopenharmony_ci	struct intel_ntb_dev *ndev = pci_get_drvdata(pdev);
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_ci	ntb_unregister_device(&ndev->ntb);
19308c2ecf20Sopenharmony_ci	ndev_deinit_debugfs(ndev);
19318c2ecf20Sopenharmony_ci	if (pdev_is_gen1(pdev) || pdev_is_gen3(pdev) || pdev_is_gen4(pdev))
19328c2ecf20Sopenharmony_ci		xeon_deinit_dev(ndev);
19338c2ecf20Sopenharmony_ci	intel_ntb_deinit_pci(ndev);
19348c2ecf20Sopenharmony_ci	kfree(ndev);
19358c2ecf20Sopenharmony_ci}
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_cistatic const struct intel_ntb_reg xeon_reg = {
19388c2ecf20Sopenharmony_ci	.poll_link		= xeon_poll_link,
19398c2ecf20Sopenharmony_ci	.link_is_up		= xeon_link_is_up,
19408c2ecf20Sopenharmony_ci	.db_ioread		= xeon_db_ioread,
19418c2ecf20Sopenharmony_ci	.db_iowrite		= xeon_db_iowrite,
19428c2ecf20Sopenharmony_ci	.db_size		= sizeof(u32),
19438c2ecf20Sopenharmony_ci	.ntb_ctl		= XEON_NTBCNTL_OFFSET,
19448c2ecf20Sopenharmony_ci	.mw_bar			= {2, 4, 5},
19458c2ecf20Sopenharmony_ci};
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_cistatic const struct intel_ntb_alt_reg xeon_pri_reg = {
19488c2ecf20Sopenharmony_ci	.db_bell		= XEON_PDOORBELL_OFFSET,
19498c2ecf20Sopenharmony_ci	.db_mask		= XEON_PDBMSK_OFFSET,
19508c2ecf20Sopenharmony_ci	.spad			= XEON_SPAD_OFFSET,
19518c2ecf20Sopenharmony_ci};
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_cistatic const struct intel_ntb_alt_reg xeon_sec_reg = {
19548c2ecf20Sopenharmony_ci	.db_bell		= XEON_SDOORBELL_OFFSET,
19558c2ecf20Sopenharmony_ci	.db_mask		= XEON_SDBMSK_OFFSET,
19568c2ecf20Sopenharmony_ci	/* second half of the scratchpads */
19578c2ecf20Sopenharmony_ci	.spad			= XEON_SPAD_OFFSET + (XEON_SPAD_COUNT << 1),
19588c2ecf20Sopenharmony_ci};
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_cistatic const struct intel_ntb_alt_reg xeon_b2b_reg = {
19618c2ecf20Sopenharmony_ci	.db_bell		= XEON_B2B_DOORBELL_OFFSET,
19628c2ecf20Sopenharmony_ci	.spad			= XEON_B2B_SPAD_OFFSET,
19638c2ecf20Sopenharmony_ci};
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_cistatic const struct intel_ntb_xlat_reg xeon_pri_xlat = {
19668c2ecf20Sopenharmony_ci	/* Note: no primary .bar0_base visible to the secondary side.
19678c2ecf20Sopenharmony_ci	 *
19688c2ecf20Sopenharmony_ci	 * The secondary side cannot get the base address stored in primary
19698c2ecf20Sopenharmony_ci	 * bars.  The base address is necessary to set the limit register to
19708c2ecf20Sopenharmony_ci	 * any value other than zero, or unlimited.
19718c2ecf20Sopenharmony_ci	 *
19728c2ecf20Sopenharmony_ci	 * WITHOUT THE BASE ADDRESS, THE SECONDARY SIDE CANNOT DISABLE the
19738c2ecf20Sopenharmony_ci	 * window by setting the limit equal to base, nor can it limit the size
19748c2ecf20Sopenharmony_ci	 * of the memory window by setting the limit to base + size.
19758c2ecf20Sopenharmony_ci	 */
19768c2ecf20Sopenharmony_ci	.bar2_limit		= XEON_PBAR23LMT_OFFSET,
19778c2ecf20Sopenharmony_ci	.bar2_xlat		= XEON_PBAR23XLAT_OFFSET,
19788c2ecf20Sopenharmony_ci};
19798c2ecf20Sopenharmony_ci
19808c2ecf20Sopenharmony_cistatic const struct intel_ntb_xlat_reg xeon_sec_xlat = {
19818c2ecf20Sopenharmony_ci	.bar0_base		= XEON_SBAR0BASE_OFFSET,
19828c2ecf20Sopenharmony_ci	.bar2_limit		= XEON_SBAR23LMT_OFFSET,
19838c2ecf20Sopenharmony_ci	.bar2_xlat		= XEON_SBAR23XLAT_OFFSET,
19848c2ecf20Sopenharmony_ci};
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_cistruct intel_b2b_addr xeon_b2b_usd_addr = {
19878c2ecf20Sopenharmony_ci	.bar2_addr64		= XEON_B2B_BAR2_ADDR64,
19888c2ecf20Sopenharmony_ci	.bar4_addr64		= XEON_B2B_BAR4_ADDR64,
19898c2ecf20Sopenharmony_ci	.bar4_addr32		= XEON_B2B_BAR4_ADDR32,
19908c2ecf20Sopenharmony_ci	.bar5_addr32		= XEON_B2B_BAR5_ADDR32,
19918c2ecf20Sopenharmony_ci};
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_cistruct intel_b2b_addr xeon_b2b_dsd_addr = {
19948c2ecf20Sopenharmony_ci	.bar2_addr64		= XEON_B2B_BAR2_ADDR64,
19958c2ecf20Sopenharmony_ci	.bar4_addr64		= XEON_B2B_BAR4_ADDR64,
19968c2ecf20Sopenharmony_ci	.bar4_addr32		= XEON_B2B_BAR4_ADDR32,
19978c2ecf20Sopenharmony_ci	.bar5_addr32		= XEON_B2B_BAR5_ADDR32,
19988c2ecf20Sopenharmony_ci};
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci/* operations for primary side of local ntb */
20018c2ecf20Sopenharmony_cistatic const struct ntb_dev_ops intel_ntb_ops = {
20028c2ecf20Sopenharmony_ci	.mw_count		= intel_ntb_mw_count,
20038c2ecf20Sopenharmony_ci	.mw_get_align		= intel_ntb_mw_get_align,
20048c2ecf20Sopenharmony_ci	.mw_set_trans		= intel_ntb_mw_set_trans,
20058c2ecf20Sopenharmony_ci	.peer_mw_count		= intel_ntb_peer_mw_count,
20068c2ecf20Sopenharmony_ci	.peer_mw_get_addr	= intel_ntb_peer_mw_get_addr,
20078c2ecf20Sopenharmony_ci	.link_is_up		= intel_ntb_link_is_up,
20088c2ecf20Sopenharmony_ci	.link_enable		= intel_ntb_link_enable,
20098c2ecf20Sopenharmony_ci	.link_disable		= intel_ntb_link_disable,
20108c2ecf20Sopenharmony_ci	.db_is_unsafe		= intel_ntb_db_is_unsafe,
20118c2ecf20Sopenharmony_ci	.db_valid_mask		= intel_ntb_db_valid_mask,
20128c2ecf20Sopenharmony_ci	.db_vector_count	= intel_ntb_db_vector_count,
20138c2ecf20Sopenharmony_ci	.db_vector_mask		= intel_ntb_db_vector_mask,
20148c2ecf20Sopenharmony_ci	.db_read		= intel_ntb_db_read,
20158c2ecf20Sopenharmony_ci	.db_clear		= intel_ntb_db_clear,
20168c2ecf20Sopenharmony_ci	.db_set_mask		= intel_ntb_db_set_mask,
20178c2ecf20Sopenharmony_ci	.db_clear_mask		= intel_ntb_db_clear_mask,
20188c2ecf20Sopenharmony_ci	.peer_db_addr		= intel_ntb_peer_db_addr,
20198c2ecf20Sopenharmony_ci	.peer_db_set		= intel_ntb_peer_db_set,
20208c2ecf20Sopenharmony_ci	.spad_is_unsafe		= intel_ntb_spad_is_unsafe,
20218c2ecf20Sopenharmony_ci	.spad_count		= intel_ntb_spad_count,
20228c2ecf20Sopenharmony_ci	.spad_read		= intel_ntb_spad_read,
20238c2ecf20Sopenharmony_ci	.spad_write		= intel_ntb_spad_write,
20248c2ecf20Sopenharmony_ci	.peer_spad_addr		= intel_ntb_peer_spad_addr,
20258c2ecf20Sopenharmony_ci	.peer_spad_read		= intel_ntb_peer_spad_read,
20268c2ecf20Sopenharmony_ci	.peer_spad_write	= intel_ntb_peer_spad_write,
20278c2ecf20Sopenharmony_ci};
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_cistatic const struct file_operations intel_ntb_debugfs_info = {
20308c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
20318c2ecf20Sopenharmony_ci	.open = simple_open,
20328c2ecf20Sopenharmony_ci	.read = ndev_debugfs_read,
20338c2ecf20Sopenharmony_ci};
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_cistatic const struct pci_device_id intel_ntb_pci_tbl[] = {
20368c2ecf20Sopenharmony_ci	/* GEN1 */
20378c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_JSF)},
20388c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_SNB)},
20398c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_IVT)},
20408c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_HSX)},
20418c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_BDX)},
20428c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_JSF)},
20438c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_SNB)},
20448c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_IVT)},
20458c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_HSX)},
20468c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_BDX)},
20478c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_JSF)},
20488c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_SNB)},
20498c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_IVT)},
20508c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_HSX)},
20518c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_BDX)},
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	/* GEN3 */
20548c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_SKX)},
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	/* GEN4 */
20578c2ecf20Sopenharmony_ci	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_ICX)},
20588c2ecf20Sopenharmony_ci	{0}
20598c2ecf20Sopenharmony_ci};
20608c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, intel_ntb_pci_tbl);
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_cistatic struct pci_driver intel_ntb_pci_driver = {
20638c2ecf20Sopenharmony_ci	.name = KBUILD_MODNAME,
20648c2ecf20Sopenharmony_ci	.id_table = intel_ntb_pci_tbl,
20658c2ecf20Sopenharmony_ci	.probe = intel_ntb_pci_probe,
20668c2ecf20Sopenharmony_ci	.remove = intel_ntb_pci_remove,
20678c2ecf20Sopenharmony_ci};
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_cistatic int __init intel_ntb_pci_driver_init(void)
20708c2ecf20Sopenharmony_ci{
20718c2ecf20Sopenharmony_ci	int ret;
20728c2ecf20Sopenharmony_ci	pr_info("%s %s\n", NTB_DESC, NTB_VER);
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	if (debugfs_initialized())
20758c2ecf20Sopenharmony_ci		debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
20768c2ecf20Sopenharmony_ci
20778c2ecf20Sopenharmony_ci	ret = pci_register_driver(&intel_ntb_pci_driver);
20788c2ecf20Sopenharmony_ci	if (ret)
20798c2ecf20Sopenharmony_ci		debugfs_remove_recursive(debugfs_dir);
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci	return ret;
20828c2ecf20Sopenharmony_ci}
20838c2ecf20Sopenharmony_cimodule_init(intel_ntb_pci_driver_init);
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_cistatic void __exit intel_ntb_pci_driver_exit(void)
20868c2ecf20Sopenharmony_ci{
20878c2ecf20Sopenharmony_ci	pci_unregister_driver(&intel_ntb_pci_driver);
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci	debugfs_remove_recursive(debugfs_dir);
20908c2ecf20Sopenharmony_ci}
20918c2ecf20Sopenharmony_cimodule_exit(intel_ntb_pci_driver_exit);
2092