1f6e51c35SDave Jiang /*
2f6e51c35SDave Jiang * This file is provided under a dual BSD/GPLv2 license. When using or
3f6e51c35SDave Jiang * redistributing this file, you may do so under either license.
4f6e51c35SDave Jiang *
5f6e51c35SDave Jiang * GPL LICENSE SUMMARY
6f6e51c35SDave Jiang *
7f6e51c35SDave Jiang * Copyright(c) 2017 Intel Corporation. All rights reserved.
8f6e51c35SDave Jiang *
9f6e51c35SDave Jiang * This program is free software; you can redistribute it and/or modify
10f6e51c35SDave Jiang * it under the terms of version 2 of the GNU General Public License as
11f6e51c35SDave Jiang * published by the Free Software Foundation.
12f6e51c35SDave Jiang *
13f6e51c35SDave Jiang * BSD LICENSE
14f6e51c35SDave Jiang *
15f6e51c35SDave Jiang * Copyright(c) 2017 Intel Corporation. All rights reserved.
16f6e51c35SDave Jiang *
17f6e51c35SDave Jiang * Redistribution and use in source and binary forms, with or without
18f6e51c35SDave Jiang * modification, are permitted provided that the following conditions
19f6e51c35SDave Jiang * are met:
20f6e51c35SDave Jiang *
21f6e51c35SDave Jiang * * Redistributions of source code must retain the above copyright
22f6e51c35SDave Jiang * notice, this list of conditions and the following disclaimer.
23f6e51c35SDave Jiang * * Redistributions in binary form must reproduce the above copy
24f6e51c35SDave Jiang * notice, this list of conditions and the following disclaimer in
25f6e51c35SDave Jiang * the documentation and/or other materials provided with the
26f6e51c35SDave Jiang * distribution.
27f6e51c35SDave Jiang * * Neither the name of Intel Corporation nor the names of its
28f6e51c35SDave Jiang * contributors may be used to endorse or promote products derived
29f6e51c35SDave Jiang * from this software without specific prior written permission.
30f6e51c35SDave Jiang *
31f6e51c35SDave Jiang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32f6e51c35SDave Jiang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33f6e51c35SDave Jiang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34f6e51c35SDave Jiang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35f6e51c35SDave Jiang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36f6e51c35SDave Jiang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37f6e51c35SDave Jiang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38f6e51c35SDave Jiang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39f6e51c35SDave Jiang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40f6e51c35SDave Jiang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41f6e51c35SDave Jiang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42f6e51c35SDave Jiang *
436c1e8ab2SDave Jiang * Intel PCIe GEN3 NTB Linux driver
44f6e51c35SDave Jiang *
45f6e51c35SDave Jiang */
46f6e51c35SDave Jiang
47f6e51c35SDave Jiang #include <linux/debugfs.h>
48f6e51c35SDave Jiang #include <linux/delay.h>
49f6e51c35SDave Jiang #include <linux/init.h>
50f6e51c35SDave Jiang #include <linux/interrupt.h>
51f6e51c35SDave Jiang #include <linux/module.h>
52f6e51c35SDave Jiang #include <linux/pci.h>
53f6e51c35SDave Jiang #include <linux/random.h>
54f6e51c35SDave Jiang #include <linux/slab.h>
55f6e51c35SDave Jiang #include <linux/ntb.h>
56f6e51c35SDave Jiang
57f6e51c35SDave Jiang #include "ntb_hw_intel.h"
58f6e51c35SDave Jiang #include "ntb_hw_gen1.h"
59f6e51c35SDave Jiang #include "ntb_hw_gen3.h"
60f6e51c35SDave Jiang
616c1e8ab2SDave Jiang static int gen3_poll_link(struct intel_ntb_dev *ndev);
626c1e8ab2SDave Jiang
636c1e8ab2SDave Jiang static const struct intel_ntb_reg gen3_reg = {
646c1e8ab2SDave Jiang .poll_link = gen3_poll_link,
65f6e51c35SDave Jiang .link_is_up = xeon_link_is_up,
666c1e8ab2SDave Jiang .db_ioread = gen3_db_ioread,
676c1e8ab2SDave Jiang .db_iowrite = gen3_db_iowrite,
68f6e51c35SDave Jiang .db_size = sizeof(u32),
696c1e8ab2SDave Jiang .ntb_ctl = GEN3_NTBCNTL_OFFSET,
70f6e51c35SDave Jiang .mw_bar = {2, 4},
71f6e51c35SDave Jiang };
72f6e51c35SDave Jiang
736c1e8ab2SDave Jiang static const struct intel_ntb_alt_reg gen3_pri_reg = {
746c1e8ab2SDave Jiang .db_bell = GEN3_EM_DOORBELL_OFFSET,
756c1e8ab2SDave Jiang .db_clear = GEN3_IM_INT_STATUS_OFFSET,
766c1e8ab2SDave Jiang .db_mask = GEN3_IM_INT_DISABLE_OFFSET,
776c1e8ab2SDave Jiang .spad = GEN3_IM_SPAD_OFFSET,
78f6e51c35SDave Jiang };
79f6e51c35SDave Jiang
806c1e8ab2SDave Jiang static const struct intel_ntb_alt_reg gen3_b2b_reg = {
816c1e8ab2SDave Jiang .db_bell = GEN3_IM_DOORBELL_OFFSET,
826c1e8ab2SDave Jiang .db_clear = GEN3_EM_INT_STATUS_OFFSET,
836c1e8ab2SDave Jiang .db_mask = GEN3_EM_INT_DISABLE_OFFSET,
846c1e8ab2SDave Jiang .spad = GEN3_B2B_SPAD_OFFSET,
85f6e51c35SDave Jiang };
86f6e51c35SDave Jiang
876c1e8ab2SDave Jiang static const struct intel_ntb_xlat_reg gen3_sec_xlat = {
886c1e8ab2SDave Jiang /* .bar0_base = GEN3_EMBAR0_OFFSET, */
896c1e8ab2SDave Jiang .bar2_limit = GEN3_IMBAR1XLMT_OFFSET,
906c1e8ab2SDave Jiang .bar2_xlat = GEN3_IMBAR1XBASE_OFFSET,
91f6e51c35SDave Jiang };
92f6e51c35SDave Jiang
gen3_poll_link(struct intel_ntb_dev * ndev)936c1e8ab2SDave Jiang static int gen3_poll_link(struct intel_ntb_dev *ndev)
94f6e51c35SDave Jiang {
95f6e51c35SDave Jiang u16 reg_val;
96f6e51c35SDave Jiang int rc;
97f6e51c35SDave Jiang
98f6e51c35SDave Jiang ndev->reg->db_iowrite(ndev->db_link_mask,
99f6e51c35SDave Jiang ndev->self_mmio +
100f6e51c35SDave Jiang ndev->self_reg->db_clear);
101f6e51c35SDave Jiang
102f6e51c35SDave Jiang rc = pci_read_config_word(ndev->ntb.pdev,
1036c1e8ab2SDave Jiang GEN3_LINK_STATUS_OFFSET, ®_val);
104f6e51c35SDave Jiang if (rc)
105f6e51c35SDave Jiang return 0;
106f6e51c35SDave Jiang
107f6e51c35SDave Jiang if (reg_val == ndev->lnk_sta)
108f6e51c35SDave Jiang return 0;
109f6e51c35SDave Jiang
110f6e51c35SDave Jiang ndev->lnk_sta = reg_val;
111f6e51c35SDave Jiang
112f6e51c35SDave Jiang return 1;
113f6e51c35SDave Jiang }
114f6e51c35SDave Jiang
gen3_init_isr(struct intel_ntb_dev * ndev)1156c1e8ab2SDave Jiang static int gen3_init_isr(struct intel_ntb_dev *ndev)
116f6e51c35SDave Jiang {
117f6e51c35SDave Jiang int i;
118f6e51c35SDave Jiang
119f6e51c35SDave Jiang /*
120f6e51c35SDave Jiang * The MSIX vectors and the interrupt status bits are not lined up
121f6e51c35SDave Jiang * on Skylake. By default the link status bit is bit 32, however it
122f6e51c35SDave Jiang * is by default MSIX vector0. We need to fixup to line them up.
123f6e51c35SDave Jiang * The vectors at reset is 1-32,0. We need to reprogram to 0-32.
124f6e51c35SDave Jiang */
125f6e51c35SDave Jiang
1266c1e8ab2SDave Jiang for (i = 0; i < GEN3_DB_MSIX_VECTOR_COUNT; i++)
1276c1e8ab2SDave Jiang iowrite8(i, ndev->self_mmio + GEN3_INTVEC_OFFSET + i);
128f6e51c35SDave Jiang
129f6e51c35SDave Jiang /* move link status down one as workaround */
130f6e51c35SDave Jiang if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) {
1316c1e8ab2SDave Jiang iowrite8(GEN3_DB_MSIX_VECTOR_COUNT - 2,
1326c1e8ab2SDave Jiang ndev->self_mmio + GEN3_INTVEC_OFFSET +
1336c1e8ab2SDave Jiang (GEN3_DB_MSIX_VECTOR_COUNT - 1));
134f6e51c35SDave Jiang }
135f6e51c35SDave Jiang
1366c1e8ab2SDave Jiang return ndev_init_isr(ndev, GEN3_DB_MSIX_VECTOR_COUNT,
1376c1e8ab2SDave Jiang GEN3_DB_MSIX_VECTOR_COUNT,
1386c1e8ab2SDave Jiang GEN3_DB_MSIX_VECTOR_SHIFT,
1396c1e8ab2SDave Jiang GEN3_DB_TOTAL_SHIFT);
140f6e51c35SDave Jiang }
141f6e51c35SDave Jiang
gen3_setup_b2b_mw(struct intel_ntb_dev * ndev,const struct intel_b2b_addr * addr,const struct intel_b2b_addr * peer_addr)1426c1e8ab2SDave Jiang static int gen3_setup_b2b_mw(struct intel_ntb_dev *ndev,
143f6e51c35SDave Jiang const struct intel_b2b_addr *addr,
144f6e51c35SDave Jiang const struct intel_b2b_addr *peer_addr)
145f6e51c35SDave Jiang {
146f6e51c35SDave Jiang struct pci_dev *pdev;
147f6e51c35SDave Jiang void __iomem *mmio;
148f6e51c35SDave Jiang phys_addr_t bar_addr;
149f6e51c35SDave Jiang
150f6e51c35SDave Jiang pdev = ndev->ntb.pdev;
151f6e51c35SDave Jiang mmio = ndev->self_mmio;
152f6e51c35SDave Jiang
153f6e51c35SDave Jiang /* setup incoming bar limits == base addrs (zero length windows) */
154f6e51c35SDave Jiang bar_addr = addr->bar2_addr64;
1556c1e8ab2SDave Jiang iowrite64(bar_addr, mmio + GEN3_IMBAR1XLMT_OFFSET);
1566c1e8ab2SDave Jiang bar_addr = ioread64(mmio + GEN3_IMBAR1XLMT_OFFSET);
157f6e51c35SDave Jiang dev_dbg(&pdev->dev, "IMBAR1XLMT %#018llx\n", bar_addr);
158f6e51c35SDave Jiang
159f6e51c35SDave Jiang bar_addr = addr->bar4_addr64;
1606c1e8ab2SDave Jiang iowrite64(bar_addr, mmio + GEN3_IMBAR2XLMT_OFFSET);
1616c1e8ab2SDave Jiang bar_addr = ioread64(mmio + GEN3_IMBAR2XLMT_OFFSET);
162f6e51c35SDave Jiang dev_dbg(&pdev->dev, "IMBAR2XLMT %#018llx\n", bar_addr);
163f6e51c35SDave Jiang
164f6e51c35SDave Jiang /* zero incoming translation addrs */
1656c1e8ab2SDave Jiang iowrite64(0, mmio + GEN3_IMBAR1XBASE_OFFSET);
1666c1e8ab2SDave Jiang iowrite64(0, mmio + GEN3_IMBAR2XBASE_OFFSET);
167f6e51c35SDave Jiang
168f6e51c35SDave Jiang ndev->peer_mmio = ndev->self_mmio;
169f6e51c35SDave Jiang
170f6e51c35SDave Jiang return 0;
171f6e51c35SDave Jiang }
172f6e51c35SDave Jiang
gen3_init_ntb(struct intel_ntb_dev * ndev)1736c1e8ab2SDave Jiang static int gen3_init_ntb(struct intel_ntb_dev *ndev)
174f6e51c35SDave Jiang {
175f6e51c35SDave Jiang int rc;
176f6e51c35SDave Jiang
177f6e51c35SDave Jiang
178f6e51c35SDave Jiang ndev->mw_count = XEON_MW_COUNT;
1796c1e8ab2SDave Jiang ndev->spad_count = GEN3_SPAD_COUNT;
1806c1e8ab2SDave Jiang ndev->db_count = GEN3_DB_COUNT;
1816c1e8ab2SDave Jiang ndev->db_link_mask = GEN3_DB_LINK_BIT;
182f6e51c35SDave Jiang
183f6e51c35SDave Jiang /* DB fixup for using 31 right now */
184f6e51c35SDave Jiang if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD)
185f6e51c35SDave Jiang ndev->db_link_mask |= BIT_ULL(31);
186f6e51c35SDave Jiang
187f6e51c35SDave Jiang switch (ndev->ntb.topo) {
188f6e51c35SDave Jiang case NTB_TOPO_B2B_USD:
189f6e51c35SDave Jiang case NTB_TOPO_B2B_DSD:
1906c1e8ab2SDave Jiang ndev->self_reg = &gen3_pri_reg;
1916c1e8ab2SDave Jiang ndev->peer_reg = &gen3_b2b_reg;
1926c1e8ab2SDave Jiang ndev->xlat_reg = &gen3_sec_xlat;
193f6e51c35SDave Jiang
194f6e51c35SDave Jiang if (ndev->ntb.topo == NTB_TOPO_B2B_USD) {
1956c1e8ab2SDave Jiang rc = gen3_setup_b2b_mw(ndev,
196f6e51c35SDave Jiang &xeon_b2b_dsd_addr,
197f6e51c35SDave Jiang &xeon_b2b_usd_addr);
198f6e51c35SDave Jiang } else {
1996c1e8ab2SDave Jiang rc = gen3_setup_b2b_mw(ndev,
200f6e51c35SDave Jiang &xeon_b2b_usd_addr,
201f6e51c35SDave Jiang &xeon_b2b_dsd_addr);
202f6e51c35SDave Jiang }
203f6e51c35SDave Jiang
204f6e51c35SDave Jiang if (rc)
205f6e51c35SDave Jiang return rc;
206f6e51c35SDave Jiang
207f6e51c35SDave Jiang /* Enable Bus Master and Memory Space on the secondary side */
208f6e51c35SDave Jiang iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
2096c1e8ab2SDave Jiang ndev->self_mmio + GEN3_SPCICMD_OFFSET);
210f6e51c35SDave Jiang
211f6e51c35SDave Jiang break;
212f6e51c35SDave Jiang
213f6e51c35SDave Jiang default:
214f6e51c35SDave Jiang return -EINVAL;
215f6e51c35SDave Jiang }
216f6e51c35SDave Jiang
217f6e51c35SDave Jiang ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
218f6e51c35SDave Jiang
219f6e51c35SDave Jiang ndev->reg->db_iowrite(ndev->db_valid_mask,
220f6e51c35SDave Jiang ndev->self_mmio +
221f6e51c35SDave Jiang ndev->self_reg->db_mask);
222f6e51c35SDave Jiang
223f6e51c35SDave Jiang return 0;
224f6e51c35SDave Jiang }
225f6e51c35SDave Jiang
gen3_init_dev(struct intel_ntb_dev * ndev)2266c1e8ab2SDave Jiang int gen3_init_dev(struct intel_ntb_dev *ndev)
227f6e51c35SDave Jiang {
228f6e51c35SDave Jiang struct pci_dev *pdev;
229f6e51c35SDave Jiang u8 ppd;
230f6e51c35SDave Jiang int rc;
231f6e51c35SDave Jiang
232f6e51c35SDave Jiang pdev = ndev->ntb.pdev;
233f6e51c35SDave Jiang
2346c1e8ab2SDave Jiang ndev->reg = &gen3_reg;
235f6e51c35SDave Jiang
236f6e51c35SDave Jiang rc = pci_read_config_byte(pdev, XEON_PPD_OFFSET, &ppd);
237f6e51c35SDave Jiang if (rc)
238f6e51c35SDave Jiang return -EIO;
239f6e51c35SDave Jiang
240f6e51c35SDave Jiang ndev->ntb.topo = xeon_ppd_topo(ndev, ppd);
241f6e51c35SDave Jiang dev_dbg(&pdev->dev, "ppd %#x topo %s\n", ppd,
242f6e51c35SDave Jiang ntb_topo_string(ndev->ntb.topo));
243f6e51c35SDave Jiang if (ndev->ntb.topo == NTB_TOPO_NONE)
244f6e51c35SDave Jiang return -EINVAL;
245f6e51c35SDave Jiang
246f6e51c35SDave Jiang ndev->hwerr_flags |= NTB_HWERR_MSIX_VECTOR32_BAD;
247f6e51c35SDave Jiang
2486c1e8ab2SDave Jiang rc = gen3_init_ntb(ndev);
249f6e51c35SDave Jiang if (rc)
250f6e51c35SDave Jiang return rc;
251f6e51c35SDave Jiang
2526c1e8ab2SDave Jiang return gen3_init_isr(ndev);
253f6e51c35SDave Jiang }
254f6e51c35SDave Jiang
ndev_ntb3_debugfs_read(struct file * filp,char __user * ubuf,size_t count,loff_t * offp)255f6e51c35SDave Jiang ssize_t ndev_ntb3_debugfs_read(struct file *filp, char __user *ubuf,
256f6e51c35SDave Jiang size_t count, loff_t *offp)
257f6e51c35SDave Jiang {
258f6e51c35SDave Jiang struct intel_ntb_dev *ndev;
259f6e51c35SDave Jiang void __iomem *mmio;
260f6e51c35SDave Jiang char *buf;
261f6e51c35SDave Jiang size_t buf_size;
262f6e51c35SDave Jiang ssize_t ret, off;
263f6e51c35SDave Jiang union { u64 v64; u32 v32; u16 v16; } u;
264f6e51c35SDave Jiang
265f6e51c35SDave Jiang ndev = filp->private_data;
266f6e51c35SDave Jiang mmio = ndev->self_mmio;
267f6e51c35SDave Jiang
268f6e51c35SDave Jiang buf_size = min(count, 0x800ul);
269f6e51c35SDave Jiang
270f6e51c35SDave Jiang buf = kmalloc(buf_size, GFP_KERNEL);
271f6e51c35SDave Jiang if (!buf)
272f6e51c35SDave Jiang return -ENOMEM;
273f6e51c35SDave Jiang
274f6e51c35SDave Jiang off = 0;
275f6e51c35SDave Jiang
276f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
277f6e51c35SDave Jiang "NTB Device Information:\n");
278f6e51c35SDave Jiang
279f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
280f6e51c35SDave Jiang "Connection Topology -\t%s\n",
281f6e51c35SDave Jiang ntb_topo_string(ndev->ntb.topo));
282f6e51c35SDave Jiang
283f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
284f6e51c35SDave Jiang "NTB CTL -\t\t%#06x\n", ndev->ntb_ctl);
285f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
286f6e51c35SDave Jiang "LNK STA -\t\t%#06x\n", ndev->lnk_sta);
287f6e51c35SDave Jiang
288f6e51c35SDave Jiang if (!ndev->reg->link_is_up(ndev))
289f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
290f6e51c35SDave Jiang "Link Status -\t\tDown\n");
291f6e51c35SDave Jiang else {
292f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
293f6e51c35SDave Jiang "Link Status -\t\tUp\n");
294f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
295f6e51c35SDave Jiang "Link Speed -\t\tPCI-E Gen %u\n",
296f6e51c35SDave Jiang NTB_LNK_STA_SPEED(ndev->lnk_sta));
297f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
298f6e51c35SDave Jiang "Link Width -\t\tx%u\n",
299f6e51c35SDave Jiang NTB_LNK_STA_WIDTH(ndev->lnk_sta));
300f6e51c35SDave Jiang }
301f6e51c35SDave Jiang
302f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
303f6e51c35SDave Jiang "Memory Window Count -\t%u\n", ndev->mw_count);
304f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
305f6e51c35SDave Jiang "Scratchpad Count -\t%u\n", ndev->spad_count);
306f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
307f6e51c35SDave Jiang "Doorbell Count -\t%u\n", ndev->db_count);
308f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
309f6e51c35SDave Jiang "Doorbell Vector Count -\t%u\n", ndev->db_vec_count);
310f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
311f6e51c35SDave Jiang "Doorbell Vector Shift -\t%u\n", ndev->db_vec_shift);
312f6e51c35SDave Jiang
313f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
314f6e51c35SDave Jiang "Doorbell Valid Mask -\t%#llx\n", ndev->db_valid_mask);
315f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
316f6e51c35SDave Jiang "Doorbell Link Mask -\t%#llx\n", ndev->db_link_mask);
317f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
318f6e51c35SDave Jiang "Doorbell Mask Cached -\t%#llx\n", ndev->db_mask);
319f6e51c35SDave Jiang
320f6e51c35SDave Jiang u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_mask);
321f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
322f6e51c35SDave Jiang "Doorbell Mask -\t\t%#llx\n", u.v64);
323f6e51c35SDave Jiang
324f6e51c35SDave Jiang u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_bell);
325f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
326f6e51c35SDave Jiang "Doorbell Bell -\t\t%#llx\n", u.v64);
327f6e51c35SDave Jiang
328f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
329f6e51c35SDave Jiang "\nNTB Incoming XLAT:\n");
330f6e51c35SDave Jiang
3316c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_IMBAR1XBASE_OFFSET);
332f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
333f6e51c35SDave Jiang "IMBAR1XBASE -\t\t%#018llx\n", u.v64);
334f6e51c35SDave Jiang
3356c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_IMBAR2XBASE_OFFSET);
336f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
337f6e51c35SDave Jiang "IMBAR2XBASE -\t\t%#018llx\n", u.v64);
338f6e51c35SDave Jiang
3396c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_IMBAR1XLMT_OFFSET);
340f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
341f6e51c35SDave Jiang "IMBAR1XLMT -\t\t\t%#018llx\n", u.v64);
342f6e51c35SDave Jiang
3436c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_IMBAR2XLMT_OFFSET);
344f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
345f6e51c35SDave Jiang "IMBAR2XLMT -\t\t\t%#018llx\n", u.v64);
346f6e51c35SDave Jiang
347f6e51c35SDave Jiang if (ntb_topo_is_b2b(ndev->ntb.topo)) {
348f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
349f6e51c35SDave Jiang "\nNTB Outgoing B2B XLAT:\n");
350f6e51c35SDave Jiang
3516c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR1XBASE_OFFSET);
352f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
353f6e51c35SDave Jiang "EMBAR1XBASE -\t\t%#018llx\n", u.v64);
354f6e51c35SDave Jiang
3556c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR2XBASE_OFFSET);
356f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
357f6e51c35SDave Jiang "EMBAR2XBASE -\t\t%#018llx\n", u.v64);
358f6e51c35SDave Jiang
3596c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR1XLMT_OFFSET);
360f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
361f6e51c35SDave Jiang "EMBAR1XLMT -\t\t%#018llx\n", u.v64);
362f6e51c35SDave Jiang
3636c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR2XLMT_OFFSET);
364f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
365f6e51c35SDave Jiang "EMBAR2XLMT -\t\t%#018llx\n", u.v64);
366f6e51c35SDave Jiang
367f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
368f6e51c35SDave Jiang "\nNTB Secondary BAR:\n");
369f6e51c35SDave Jiang
3706c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR0_OFFSET);
371f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
372f6e51c35SDave Jiang "EMBAR0 -\t\t%#018llx\n", u.v64);
373f6e51c35SDave Jiang
3746c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR1_OFFSET);
375f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
376f6e51c35SDave Jiang "EMBAR1 -\t\t%#018llx\n", u.v64);
377f6e51c35SDave Jiang
3786c1e8ab2SDave Jiang u.v64 = ioread64(mmio + GEN3_EMBAR2_OFFSET);
379f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
380f6e51c35SDave Jiang "EMBAR2 -\t\t%#018llx\n", u.v64);
381f6e51c35SDave Jiang }
382f6e51c35SDave Jiang
383f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
384f6e51c35SDave Jiang "\nNTB Statistics:\n");
385f6e51c35SDave Jiang
3866c1e8ab2SDave Jiang u.v16 = ioread16(mmio + GEN3_USMEMMISS_OFFSET);
387f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
388f6e51c35SDave Jiang "Upstream Memory Miss -\t%u\n", u.v16);
389f6e51c35SDave Jiang
390f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
391f6e51c35SDave Jiang "\nNTB Hardware Errors:\n");
392f6e51c35SDave Jiang
393f6e51c35SDave Jiang if (!pci_read_config_word(ndev->ntb.pdev,
3946c1e8ab2SDave Jiang GEN3_DEVSTS_OFFSET, &u.v16))
395f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
396f6e51c35SDave Jiang "DEVSTS -\t\t%#06x\n", u.v16);
397f6e51c35SDave Jiang
398f6e51c35SDave Jiang if (!pci_read_config_word(ndev->ntb.pdev,
3996c1e8ab2SDave Jiang GEN3_LINK_STATUS_OFFSET, &u.v16))
400f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
401f6e51c35SDave Jiang "LNKSTS -\t\t%#06x\n", u.v16);
402f6e51c35SDave Jiang
403f6e51c35SDave Jiang if (!pci_read_config_dword(ndev->ntb.pdev,
4046c1e8ab2SDave Jiang GEN3_UNCERRSTS_OFFSET, &u.v32))
405f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
406f6e51c35SDave Jiang "UNCERRSTS -\t\t%#06x\n", u.v32);
407f6e51c35SDave Jiang
408f6e51c35SDave Jiang if (!pci_read_config_dword(ndev->ntb.pdev,
4096c1e8ab2SDave Jiang GEN3_CORERRSTS_OFFSET, &u.v32))
410f6e51c35SDave Jiang off += scnprintf(buf + off, buf_size - off,
411f6e51c35SDave Jiang "CORERRSTS -\t\t%#06x\n", u.v32);
412f6e51c35SDave Jiang
413f6e51c35SDave Jiang ret = simple_read_from_buffer(ubuf, count, offp, buf, off);
414f6e51c35SDave Jiang kfree(buf);
415f6e51c35SDave Jiang return ret;
416f6e51c35SDave Jiang }
417f6e51c35SDave Jiang
intel_ntb3_link_enable(struct ntb_dev * ntb,enum ntb_speed max_speed,enum ntb_width max_width)418*26bfe3d0SDave Jiang int intel_ntb3_link_enable(struct ntb_dev *ntb, enum ntb_speed max_speed,
419f6e51c35SDave Jiang enum ntb_width max_width)
420f6e51c35SDave Jiang {
421f6e51c35SDave Jiang struct intel_ntb_dev *ndev;
422f6e51c35SDave Jiang u32 ntb_ctl;
423f6e51c35SDave Jiang
424f6e51c35SDave Jiang ndev = container_of(ntb, struct intel_ntb_dev, ntb);
425f6e51c35SDave Jiang
426f6e51c35SDave Jiang dev_dbg(&ntb->pdev->dev,
427f6e51c35SDave Jiang "Enabling link with max_speed %d max_width %d\n",
428f6e51c35SDave Jiang max_speed, max_width);
429f6e51c35SDave Jiang
430f6e51c35SDave Jiang if (max_speed != NTB_SPEED_AUTO)
431f6e51c35SDave Jiang dev_dbg(&ntb->pdev->dev, "ignoring max_speed %d\n", max_speed);
432f6e51c35SDave Jiang if (max_width != NTB_WIDTH_AUTO)
433f6e51c35SDave Jiang dev_dbg(&ntb->pdev->dev, "ignoring max_width %d\n", max_width);
434f6e51c35SDave Jiang
435f6e51c35SDave Jiang ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
436f6e51c35SDave Jiang ntb_ctl &= ~(NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK);
437f6e51c35SDave Jiang ntb_ctl |= NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;
438f6e51c35SDave Jiang ntb_ctl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;
439f6e51c35SDave Jiang iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
440f6e51c35SDave Jiang
441f6e51c35SDave Jiang return 0;
442f6e51c35SDave Jiang }
intel_ntb3_mw_set_trans(struct ntb_dev * ntb,int pidx,int idx,dma_addr_t addr,resource_size_t size)443f6e51c35SDave Jiang static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
444f6e51c35SDave Jiang dma_addr_t addr, resource_size_t size)
445f6e51c35SDave Jiang {
446f6e51c35SDave Jiang struct intel_ntb_dev *ndev = ntb_ndev(ntb);
447f6e51c35SDave Jiang unsigned long xlat_reg, limit_reg;
448f6e51c35SDave Jiang resource_size_t bar_size, mw_size;
449f6e51c35SDave Jiang void __iomem *mmio;
450f6e51c35SDave Jiang u64 base, limit, reg_val;
451f6e51c35SDave Jiang int bar;
452f6e51c35SDave Jiang
453f6e51c35SDave Jiang if (pidx != NTB_DEF_PEER_IDX)
454f6e51c35SDave Jiang return -EINVAL;
455f6e51c35SDave Jiang
456f6e51c35SDave Jiang if (idx >= ndev->b2b_idx && !ndev->b2b_off)
457f6e51c35SDave Jiang idx += 1;
458f6e51c35SDave Jiang
459f6e51c35SDave Jiang bar = ndev_mw_to_bar(ndev, idx);
460f6e51c35SDave Jiang if (bar < 0)
461f6e51c35SDave Jiang return bar;
462f6e51c35SDave Jiang
463f6e51c35SDave Jiang bar_size = pci_resource_len(ndev->ntb.pdev, bar);
464f6e51c35SDave Jiang
465f6e51c35SDave Jiang if (idx == ndev->b2b_idx)
466f6e51c35SDave Jiang mw_size = bar_size - ndev->b2b_off;
467f6e51c35SDave Jiang else
468f6e51c35SDave Jiang mw_size = bar_size;
469f6e51c35SDave Jiang
470f6e51c35SDave Jiang /* hardware requires that addr is aligned to bar size */
471f6e51c35SDave Jiang if (addr & (bar_size - 1))
472f6e51c35SDave Jiang return -EINVAL;
473f6e51c35SDave Jiang
474f6e51c35SDave Jiang /* make sure the range fits in the usable mw size */
475f6e51c35SDave Jiang if (size > mw_size)
476f6e51c35SDave Jiang return -EINVAL;
477f6e51c35SDave Jiang
478f6e51c35SDave Jiang mmio = ndev->self_mmio;
479f6e51c35SDave Jiang xlat_reg = ndev->xlat_reg->bar2_xlat + (idx * 0x10);
480f6e51c35SDave Jiang limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10);
481f6e51c35SDave Jiang base = pci_resource_start(ndev->ntb.pdev, bar);
482f6e51c35SDave Jiang
483f6e51c35SDave Jiang /* Set the limit if supported, if size is not mw_size */
484f6e51c35SDave Jiang if (limit_reg && size != mw_size)
485f6e51c35SDave Jiang limit = base + size;
486f6e51c35SDave Jiang else
487f6e51c35SDave Jiang limit = base + mw_size;
488f6e51c35SDave Jiang
489f6e51c35SDave Jiang /* set and verify setting the translation address */
490f6e51c35SDave Jiang iowrite64(addr, mmio + xlat_reg);
491f6e51c35SDave Jiang reg_val = ioread64(mmio + xlat_reg);
492f6e51c35SDave Jiang if (reg_val != addr) {
493f6e51c35SDave Jiang iowrite64(0, mmio + xlat_reg);
494f6e51c35SDave Jiang return -EIO;
495f6e51c35SDave Jiang }
496f6e51c35SDave Jiang
497f6e51c35SDave Jiang dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXBASE: %#Lx\n", bar, reg_val);
498f6e51c35SDave Jiang
499f6e51c35SDave Jiang /* set and verify setting the limit */
500f6e51c35SDave Jiang iowrite64(limit, mmio + limit_reg);
501f6e51c35SDave Jiang reg_val = ioread64(mmio + limit_reg);
502f6e51c35SDave Jiang if (reg_val != limit) {
503f6e51c35SDave Jiang iowrite64(base, mmio + limit_reg);
504f6e51c35SDave Jiang iowrite64(0, mmio + xlat_reg);
505f6e51c35SDave Jiang return -EIO;
506f6e51c35SDave Jiang }
507f6e51c35SDave Jiang
508f6e51c35SDave Jiang dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXLMT: %#Lx\n", bar, reg_val);
509f6e51c35SDave Jiang
510f6e51c35SDave Jiang /* setup the EP */
511f6e51c35SDave Jiang limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10) + 0x4000;
5126c1e8ab2SDave Jiang base = ioread64(mmio + GEN3_EMBAR1_OFFSET + (8 * idx));
513f6e51c35SDave Jiang base &= ~0xf;
514f6e51c35SDave Jiang
515f6e51c35SDave Jiang if (limit_reg && size != mw_size)
516f6e51c35SDave Jiang limit = base + size;
517f6e51c35SDave Jiang else
518f6e51c35SDave Jiang limit = base + mw_size;
519f6e51c35SDave Jiang
520f6e51c35SDave Jiang /* set and verify setting the limit */
521f6e51c35SDave Jiang iowrite64(limit, mmio + limit_reg);
522f6e51c35SDave Jiang reg_val = ioread64(mmio + limit_reg);
523f6e51c35SDave Jiang if (reg_val != limit) {
524f6e51c35SDave Jiang iowrite64(base, mmio + limit_reg);
525f6e51c35SDave Jiang iowrite64(0, mmio + xlat_reg);
526f6e51c35SDave Jiang return -EIO;
527f6e51c35SDave Jiang }
528f6e51c35SDave Jiang
529f6e51c35SDave Jiang dev_dbg(&ntb->pdev->dev, "BAR %d EMBARXLMT: %#Lx\n", bar, reg_val);
530f6e51c35SDave Jiang
531f6e51c35SDave Jiang return 0;
532f6e51c35SDave Jiang }
533f6e51c35SDave Jiang
intel_ntb3_peer_db_addr(struct ntb_dev * ntb,phys_addr_t * db_addr,resource_size_t * db_size,u64 * db_data,int db_bit)534*26bfe3d0SDave Jiang int intel_ntb3_peer_db_addr(struct ntb_dev *ntb, phys_addr_t *db_addr,
535ebb09b33SLeonid Ravich resource_size_t *db_size,
536ebb09b33SLeonid Ravich u64 *db_data, int db_bit)
537ebb09b33SLeonid Ravich {
538ebb09b33SLeonid Ravich phys_addr_t db_addr_base;
539ebb09b33SLeonid Ravich struct intel_ntb_dev *ndev = ntb_ndev(ntb);
540ebb09b33SLeonid Ravich
541ebb09b33SLeonid Ravich if (unlikely(db_bit >= BITS_PER_LONG_LONG))
542ebb09b33SLeonid Ravich return -EINVAL;
543ebb09b33SLeonid Ravich
544ebb09b33SLeonid Ravich if (unlikely(BIT_ULL(db_bit) & ~ntb_ndev(ntb)->db_valid_mask))
545ebb09b33SLeonid Ravich return -EINVAL;
546ebb09b33SLeonid Ravich
547ebb09b33SLeonid Ravich ndev_db_addr(ndev, &db_addr_base, db_size, ndev->peer_addr,
548ebb09b33SLeonid Ravich ndev->peer_reg->db_bell);
549ebb09b33SLeonid Ravich
550ebb09b33SLeonid Ravich if (db_addr) {
551ebb09b33SLeonid Ravich *db_addr = db_addr_base + (db_bit * 4);
552ebb09b33SLeonid Ravich dev_dbg(&ndev->ntb.pdev->dev, "Peer db addr %llx db bit %d\n",
553ebb09b33SLeonid Ravich *db_addr, db_bit);
554ebb09b33SLeonid Ravich }
555ebb09b33SLeonid Ravich
556ebb09b33SLeonid Ravich if (db_data) {
557ebb09b33SLeonid Ravich *db_data = 1;
558ebb09b33SLeonid Ravich dev_dbg(&ndev->ntb.pdev->dev, "Peer db data %llx db bit %d\n",
559ebb09b33SLeonid Ravich *db_data, db_bit);
560ebb09b33SLeonid Ravich }
561ebb09b33SLeonid Ravich
562ebb09b33SLeonid Ravich return 0;
563ebb09b33SLeonid Ravich }
564ebb09b33SLeonid Ravich
intel_ntb3_peer_db_set(struct ntb_dev * ntb,u64 db_bits)565*26bfe3d0SDave Jiang int intel_ntb3_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
566f6e51c35SDave Jiang {
567f6e51c35SDave Jiang struct intel_ntb_dev *ndev = ntb_ndev(ntb);
568f6e51c35SDave Jiang int bit;
569f6e51c35SDave Jiang
570f6e51c35SDave Jiang if (db_bits & ~ndev->db_valid_mask)
571f6e51c35SDave Jiang return -EINVAL;
572f6e51c35SDave Jiang
573f6e51c35SDave Jiang while (db_bits) {
574f6e51c35SDave Jiang bit = __ffs(db_bits);
575f6e51c35SDave Jiang iowrite32(1, ndev->peer_mmio +
576f6e51c35SDave Jiang ndev->peer_reg->db_bell + (bit * 4));
577f6e51c35SDave Jiang db_bits &= db_bits - 1;
578f6e51c35SDave Jiang }
579f6e51c35SDave Jiang
580f6e51c35SDave Jiang return 0;
581f6e51c35SDave Jiang }
582f6e51c35SDave Jiang
intel_ntb3_db_read(struct ntb_dev * ntb)583*26bfe3d0SDave Jiang u64 intel_ntb3_db_read(struct ntb_dev *ntb)
584f6e51c35SDave Jiang {
585f6e51c35SDave Jiang struct intel_ntb_dev *ndev = ntb_ndev(ntb);
586f6e51c35SDave Jiang
587f6e51c35SDave Jiang return ndev_db_read(ndev,
588f6e51c35SDave Jiang ndev->self_mmio +
589f6e51c35SDave Jiang ndev->self_reg->db_clear);
590f6e51c35SDave Jiang }
591f6e51c35SDave Jiang
intel_ntb3_db_clear(struct ntb_dev * ntb,u64 db_bits)592*26bfe3d0SDave Jiang int intel_ntb3_db_clear(struct ntb_dev *ntb, u64 db_bits)
593f6e51c35SDave Jiang {
594f6e51c35SDave Jiang struct intel_ntb_dev *ndev = ntb_ndev(ntb);
595f6e51c35SDave Jiang
596f6e51c35SDave Jiang return ndev_db_write(ndev, db_bits,
597f6e51c35SDave Jiang ndev->self_mmio +
598f6e51c35SDave Jiang ndev->self_reg->db_clear);
599f6e51c35SDave Jiang }
600f6e51c35SDave Jiang
601f6e51c35SDave Jiang const struct ntb_dev_ops intel_ntb3_ops = {
602f6e51c35SDave Jiang .mw_count = intel_ntb_mw_count,
603f6e51c35SDave Jiang .mw_get_align = intel_ntb_mw_get_align,
604f6e51c35SDave Jiang .mw_set_trans = intel_ntb3_mw_set_trans,
605f6e51c35SDave Jiang .peer_mw_count = intel_ntb_peer_mw_count,
606f6e51c35SDave Jiang .peer_mw_get_addr = intel_ntb_peer_mw_get_addr,
607f6e51c35SDave Jiang .link_is_up = intel_ntb_link_is_up,
608f6e51c35SDave Jiang .link_enable = intel_ntb3_link_enable,
609f6e51c35SDave Jiang .link_disable = intel_ntb_link_disable,
610f6e51c35SDave Jiang .db_valid_mask = intel_ntb_db_valid_mask,
611f6e51c35SDave Jiang .db_vector_count = intel_ntb_db_vector_count,
612f6e51c35SDave Jiang .db_vector_mask = intel_ntb_db_vector_mask,
613f6e51c35SDave Jiang .db_read = intel_ntb3_db_read,
614f6e51c35SDave Jiang .db_clear = intel_ntb3_db_clear,
615f6e51c35SDave Jiang .db_set_mask = intel_ntb_db_set_mask,
616f6e51c35SDave Jiang .db_clear_mask = intel_ntb_db_clear_mask,
617ebb09b33SLeonid Ravich .peer_db_addr = intel_ntb3_peer_db_addr,
618f6e51c35SDave Jiang .peer_db_set = intel_ntb3_peer_db_set,
619f6e51c35SDave Jiang .spad_is_unsafe = intel_ntb_spad_is_unsafe,
620f6e51c35SDave Jiang .spad_count = intel_ntb_spad_count,
621f6e51c35SDave Jiang .spad_read = intel_ntb_spad_read,
622f6e51c35SDave Jiang .spad_write = intel_ntb_spad_write,
623f6e51c35SDave Jiang .peer_spad_addr = intel_ntb_peer_spad_addr,
624f6e51c35SDave Jiang .peer_spad_read = intel_ntb_peer_spad_read,
625f6e51c35SDave Jiang .peer_spad_write = intel_ntb_peer_spad_write,
626f6e51c35SDave Jiang };
627f6e51c35SDave Jiang
628