ntb_hw_gen3.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /*
  2. * This file is provided under a dual BSD/GPLv2 license. When using or
  3. * redistributing this file, you may do so under either license.
  4. *
  5. * GPL LICENSE SUMMARY
  6. *
  7. * Copyright(c) 2017 Intel Corporation. All rights reserved.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of version 2 of the GNU General Public License as
  11. * published by the Free Software Foundation.
  12. *
  13. * BSD LICENSE
  14. *
  15. * Copyright(c) 2017 Intel Corporation. All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms, with or without
  18. * modification, are permitted provided that the following conditions
  19. * are met:
  20. *
  21. * * Redistributions of source code must retain the above copyright
  22. * notice, this list of conditions and the following disclaimer.
  23. * * Redistributions in binary form must reproduce the above copy
  24. * notice, this list of conditions and the following disclaimer in
  25. * the documentation and/or other materials provided with the
  26. * distribution.
  27. * * Neither the name of Intel Corporation nor the names of its
  28. * contributors may be used to endorse or promote products derived
  29. * from this software without specific prior written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  34. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  37. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  38. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  39. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  40. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  41. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. *
  43. * Intel PCIe GEN3 NTB Linux driver
  44. *
  45. */
  46. #include <linux/debugfs.h>
  47. #include <linux/delay.h>
  48. #include <linux/init.h>
  49. #include <linux/interrupt.h>
  50. #include <linux/module.h>
  51. #include <linux/pci.h>
  52. #include <linux/random.h>
  53. #include <linux/slab.h>
  54. #include <linux/ntb.h>
  55. #include "ntb_hw_intel.h"
  56. #include "ntb_hw_gen1.h"
  57. #include "ntb_hw_gen3.h"
  58. static int gen3_poll_link(struct intel_ntb_dev *ndev);
  59. static const struct intel_ntb_reg gen3_reg = {
  60. .poll_link = gen3_poll_link,
  61. .link_is_up = xeon_link_is_up,
  62. .db_ioread = gen3_db_ioread,
  63. .db_iowrite = gen3_db_iowrite,
  64. .db_size = sizeof(u32),
  65. .ntb_ctl = GEN3_NTBCNTL_OFFSET,
  66. .mw_bar = {2, 4},
  67. };
  68. static const struct intel_ntb_alt_reg gen3_pri_reg = {
  69. .db_bell = GEN3_EM_DOORBELL_OFFSET,
  70. .db_clear = GEN3_IM_INT_STATUS_OFFSET,
  71. .db_mask = GEN3_IM_INT_DISABLE_OFFSET,
  72. .spad = GEN3_IM_SPAD_OFFSET,
  73. };
  74. static const struct intel_ntb_alt_reg gen3_b2b_reg = {
  75. .db_bell = GEN3_IM_DOORBELL_OFFSET,
  76. .db_clear = GEN3_EM_INT_STATUS_OFFSET,
  77. .db_mask = GEN3_EM_INT_DISABLE_OFFSET,
  78. .spad = GEN3_B2B_SPAD_OFFSET,
  79. };
  80. static const struct intel_ntb_xlat_reg gen3_sec_xlat = {
  81. /* .bar0_base = GEN3_EMBAR0_OFFSET, */
  82. .bar2_limit = GEN3_IMBAR1XLMT_OFFSET,
  83. .bar2_xlat = GEN3_IMBAR1XBASE_OFFSET,
  84. };
  85. static int gen3_poll_link(struct intel_ntb_dev *ndev)
  86. {
  87. u16 reg_val;
  88. int rc;
  89. ndev->reg->db_iowrite(ndev->db_link_mask,
  90. ndev->self_mmio +
  91. ndev->self_reg->db_clear);
  92. rc = pci_read_config_word(ndev->ntb.pdev,
  93. GEN3_LINK_STATUS_OFFSET, &reg_val);
  94. if (rc)
  95. return 0;
  96. if (reg_val == ndev->lnk_sta)
  97. return 0;
  98. ndev->lnk_sta = reg_val;
  99. return 1;
  100. }
  101. static int gen3_init_isr(struct intel_ntb_dev *ndev)
  102. {
  103. int i;
  104. /*
  105. * The MSIX vectors and the interrupt status bits are not lined up
  106. * on Skylake. By default the link status bit is bit 32, however it
  107. * is by default MSIX vector0. We need to fixup to line them up.
  108. * The vectors at reset is 1-32,0. We need to reprogram to 0-32.
  109. */
  110. for (i = 0; i < GEN3_DB_MSIX_VECTOR_COUNT; i++)
  111. iowrite8(i, ndev->self_mmio + GEN3_INTVEC_OFFSET + i);
  112. /* move link status down one as workaround */
  113. if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) {
  114. iowrite8(GEN3_DB_MSIX_VECTOR_COUNT - 2,
  115. ndev->self_mmio + GEN3_INTVEC_OFFSET +
  116. (GEN3_DB_MSIX_VECTOR_COUNT - 1));
  117. }
  118. return ndev_init_isr(ndev, GEN3_DB_MSIX_VECTOR_COUNT,
  119. GEN3_DB_MSIX_VECTOR_COUNT,
  120. GEN3_DB_MSIX_VECTOR_SHIFT,
  121. GEN3_DB_TOTAL_SHIFT);
  122. }
  123. static int gen3_setup_b2b_mw(struct intel_ntb_dev *ndev,
  124. const struct intel_b2b_addr *addr,
  125. const struct intel_b2b_addr *peer_addr)
  126. {
  127. struct pci_dev *pdev;
  128. void __iomem *mmio;
  129. phys_addr_t bar_addr;
  130. pdev = ndev->ntb.pdev;
  131. mmio = ndev->self_mmio;
  132. /* setup incoming bar limits == base addrs (zero length windows) */
  133. bar_addr = addr->bar2_addr64;
  134. iowrite64(bar_addr, mmio + GEN3_IMBAR1XLMT_OFFSET);
  135. bar_addr = ioread64(mmio + GEN3_IMBAR1XLMT_OFFSET);
  136. dev_dbg(&pdev->dev, "IMBAR1XLMT %#018llx\n", bar_addr);
  137. bar_addr = addr->bar4_addr64;
  138. iowrite64(bar_addr, mmio + GEN3_IMBAR2XLMT_OFFSET);
  139. bar_addr = ioread64(mmio + GEN3_IMBAR2XLMT_OFFSET);
  140. dev_dbg(&pdev->dev, "IMBAR2XLMT %#018llx\n", bar_addr);
  141. /* zero incoming translation addrs */
  142. iowrite64(0, mmio + GEN3_IMBAR1XBASE_OFFSET);
  143. iowrite64(0, mmio + GEN3_IMBAR2XBASE_OFFSET);
  144. ndev->peer_mmio = ndev->self_mmio;
  145. return 0;
  146. }
  147. static int gen3_init_ntb(struct intel_ntb_dev *ndev)
  148. {
  149. int rc;
  150. ndev->mw_count = XEON_MW_COUNT;
  151. ndev->spad_count = GEN3_SPAD_COUNT;
  152. ndev->db_count = GEN3_DB_COUNT;
  153. ndev->db_link_mask = GEN3_DB_LINK_BIT;
  154. /* DB fixup for using 31 right now */
  155. if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD)
  156. ndev->db_link_mask |= BIT_ULL(31);
  157. switch (ndev->ntb.topo) {
  158. case NTB_TOPO_B2B_USD:
  159. case NTB_TOPO_B2B_DSD:
  160. ndev->self_reg = &gen3_pri_reg;
  161. ndev->peer_reg = &gen3_b2b_reg;
  162. ndev->xlat_reg = &gen3_sec_xlat;
  163. if (ndev->ntb.topo == NTB_TOPO_B2B_USD) {
  164. rc = gen3_setup_b2b_mw(ndev,
  165. &xeon_b2b_dsd_addr,
  166. &xeon_b2b_usd_addr);
  167. } else {
  168. rc = gen3_setup_b2b_mw(ndev,
  169. &xeon_b2b_usd_addr,
  170. &xeon_b2b_dsd_addr);
  171. }
  172. if (rc)
  173. return rc;
  174. /* Enable Bus Master and Memory Space on the secondary side */
  175. iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
  176. ndev->self_mmio + GEN3_SPCICMD_OFFSET);
  177. break;
  178. default:
  179. return -EINVAL;
  180. }
  181. ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
  182. ndev->reg->db_iowrite(ndev->db_valid_mask,
  183. ndev->self_mmio +
  184. ndev->self_reg->db_mask);
  185. return 0;
  186. }
  187. int gen3_init_dev(struct intel_ntb_dev *ndev)
  188. {
  189. struct pci_dev *pdev;
  190. u8 ppd;
  191. int rc;
  192. pdev = ndev->ntb.pdev;
  193. ndev->reg = &gen3_reg;
  194. rc = pci_read_config_byte(pdev, XEON_PPD_OFFSET, &ppd);
  195. if (rc)
  196. return -EIO;
  197. ndev->ntb.topo = xeon_ppd_topo(ndev, ppd);
  198. dev_dbg(&pdev->dev, "ppd %#x topo %s\n", ppd,
  199. ntb_topo_string(ndev->ntb.topo));
  200. if (ndev->ntb.topo == NTB_TOPO_NONE)
  201. return -EINVAL;
  202. ndev->hwerr_flags |= NTB_HWERR_MSIX_VECTOR32_BAD;
  203. rc = gen3_init_ntb(ndev);
  204. if (rc)
  205. return rc;
  206. return gen3_init_isr(ndev);
  207. }
  208. ssize_t ndev_ntb3_debugfs_read(struct file *filp, char __user *ubuf,
  209. size_t count, loff_t *offp)
  210. {
  211. struct intel_ntb_dev *ndev;
  212. void __iomem *mmio;
  213. char *buf;
  214. size_t buf_size;
  215. ssize_t ret, off;
  216. union { u64 v64; u32 v32; u16 v16; } u;
  217. ndev = filp->private_data;
  218. mmio = ndev->self_mmio;
  219. buf_size = min(count, 0x800ul);
  220. buf = kmalloc(buf_size, GFP_KERNEL);
  221. if (!buf)
  222. return -ENOMEM;
  223. off = 0;
  224. off += scnprintf(buf + off, buf_size - off,
  225. "NTB Device Information:\n");
  226. off += scnprintf(buf + off, buf_size - off,
  227. "Connection Topology -\t%s\n",
  228. ntb_topo_string(ndev->ntb.topo));
  229. off += scnprintf(buf + off, buf_size - off,
  230. "NTB CTL -\t\t%#06x\n", ndev->ntb_ctl);
  231. off += scnprintf(buf + off, buf_size - off,
  232. "LNK STA -\t\t%#06x\n", ndev->lnk_sta);
  233. if (!ndev->reg->link_is_up(ndev))
  234. off += scnprintf(buf + off, buf_size - off,
  235. "Link Status -\t\tDown\n");
  236. else {
  237. off += scnprintf(buf + off, buf_size - off,
  238. "Link Status -\t\tUp\n");
  239. off += scnprintf(buf + off, buf_size - off,
  240. "Link Speed -\t\tPCI-E Gen %u\n",
  241. NTB_LNK_STA_SPEED(ndev->lnk_sta));
  242. off += scnprintf(buf + off, buf_size - off,
  243. "Link Width -\t\tx%u\n",
  244. NTB_LNK_STA_WIDTH(ndev->lnk_sta));
  245. }
  246. off += scnprintf(buf + off, buf_size - off,
  247. "Memory Window Count -\t%u\n", ndev->mw_count);
  248. off += scnprintf(buf + off, buf_size - off,
  249. "Scratchpad Count -\t%u\n", ndev->spad_count);
  250. off += scnprintf(buf + off, buf_size - off,
  251. "Doorbell Count -\t%u\n", ndev->db_count);
  252. off += scnprintf(buf + off, buf_size - off,
  253. "Doorbell Vector Count -\t%u\n", ndev->db_vec_count);
  254. off += scnprintf(buf + off, buf_size - off,
  255. "Doorbell Vector Shift -\t%u\n", ndev->db_vec_shift);
  256. off += scnprintf(buf + off, buf_size - off,
  257. "Doorbell Valid Mask -\t%#llx\n", ndev->db_valid_mask);
  258. off += scnprintf(buf + off, buf_size - off,
  259. "Doorbell Link Mask -\t%#llx\n", ndev->db_link_mask);
  260. off += scnprintf(buf + off, buf_size - off,
  261. "Doorbell Mask Cached -\t%#llx\n", ndev->db_mask);
  262. u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_mask);
  263. off += scnprintf(buf + off, buf_size - off,
  264. "Doorbell Mask -\t\t%#llx\n", u.v64);
  265. u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_bell);
  266. off += scnprintf(buf + off, buf_size - off,
  267. "Doorbell Bell -\t\t%#llx\n", u.v64);
  268. off += scnprintf(buf + off, buf_size - off,
  269. "\nNTB Incoming XLAT:\n");
  270. u.v64 = ioread64(mmio + GEN3_IMBAR1XBASE_OFFSET);
  271. off += scnprintf(buf + off, buf_size - off,
  272. "IMBAR1XBASE -\t\t%#018llx\n", u.v64);
  273. u.v64 = ioread64(mmio + GEN3_IMBAR2XBASE_OFFSET);
  274. off += scnprintf(buf + off, buf_size - off,
  275. "IMBAR2XBASE -\t\t%#018llx\n", u.v64);
  276. u.v64 = ioread64(mmio + GEN3_IMBAR1XLMT_OFFSET);
  277. off += scnprintf(buf + off, buf_size - off,
  278. "IMBAR1XLMT -\t\t\t%#018llx\n", u.v64);
  279. u.v64 = ioread64(mmio + GEN3_IMBAR2XLMT_OFFSET);
  280. off += scnprintf(buf + off, buf_size - off,
  281. "IMBAR2XLMT -\t\t\t%#018llx\n", u.v64);
  282. if (ntb_topo_is_b2b(ndev->ntb.topo)) {
  283. off += scnprintf(buf + off, buf_size - off,
  284. "\nNTB Outgoing B2B XLAT:\n");
  285. u.v64 = ioread64(mmio + GEN3_EMBAR1XBASE_OFFSET);
  286. off += scnprintf(buf + off, buf_size - off,
  287. "EMBAR1XBASE -\t\t%#018llx\n", u.v64);
  288. u.v64 = ioread64(mmio + GEN3_EMBAR2XBASE_OFFSET);
  289. off += scnprintf(buf + off, buf_size - off,
  290. "EMBAR2XBASE -\t\t%#018llx\n", u.v64);
  291. u.v64 = ioread64(mmio + GEN3_EMBAR1XLMT_OFFSET);
  292. off += scnprintf(buf + off, buf_size - off,
  293. "EMBAR1XLMT -\t\t%#018llx\n", u.v64);
  294. u.v64 = ioread64(mmio + GEN3_EMBAR2XLMT_OFFSET);
  295. off += scnprintf(buf + off, buf_size - off,
  296. "EMBAR2XLMT -\t\t%#018llx\n", u.v64);
  297. off += scnprintf(buf + off, buf_size - off,
  298. "\nNTB Secondary BAR:\n");
  299. u.v64 = ioread64(mmio + GEN3_EMBAR0_OFFSET);
  300. off += scnprintf(buf + off, buf_size - off,
  301. "EMBAR0 -\t\t%#018llx\n", u.v64);
  302. u.v64 = ioread64(mmio + GEN3_EMBAR1_OFFSET);
  303. off += scnprintf(buf + off, buf_size - off,
  304. "EMBAR1 -\t\t%#018llx\n", u.v64);
  305. u.v64 = ioread64(mmio + GEN3_EMBAR2_OFFSET);
  306. off += scnprintf(buf + off, buf_size - off,
  307. "EMBAR2 -\t\t%#018llx\n", u.v64);
  308. }
  309. off += scnprintf(buf + off, buf_size - off,
  310. "\nNTB Statistics:\n");
  311. u.v16 = ioread16(mmio + GEN3_USMEMMISS_OFFSET);
  312. off += scnprintf(buf + off, buf_size - off,
  313. "Upstream Memory Miss -\t%u\n", u.v16);
  314. off += scnprintf(buf + off, buf_size - off,
  315. "\nNTB Hardware Errors:\n");
  316. if (!pci_read_config_word(ndev->ntb.pdev,
  317. GEN3_DEVSTS_OFFSET, &u.v16))
  318. off += scnprintf(buf + off, buf_size - off,
  319. "DEVSTS -\t\t%#06x\n", u.v16);
  320. if (!pci_read_config_word(ndev->ntb.pdev,
  321. GEN3_LINK_STATUS_OFFSET, &u.v16))
  322. off += scnprintf(buf + off, buf_size - off,
  323. "LNKSTS -\t\t%#06x\n", u.v16);
  324. if (!pci_read_config_dword(ndev->ntb.pdev,
  325. GEN3_UNCERRSTS_OFFSET, &u.v32))
  326. off += scnprintf(buf + off, buf_size - off,
  327. "UNCERRSTS -\t\t%#06x\n", u.v32);
  328. if (!pci_read_config_dword(ndev->ntb.pdev,
  329. GEN3_CORERRSTS_OFFSET, &u.v32))
  330. off += scnprintf(buf + off, buf_size - off,
  331. "CORERRSTS -\t\t%#06x\n", u.v32);
  332. ret = simple_read_from_buffer(ubuf, count, offp, buf, off);
  333. kfree(buf);
  334. return ret;
  335. }
  336. static int intel_ntb3_link_enable(struct ntb_dev *ntb,
  337. enum ntb_speed max_speed,
  338. enum ntb_width max_width)
  339. {
  340. struct intel_ntb_dev *ndev;
  341. u32 ntb_ctl;
  342. ndev = container_of(ntb, struct intel_ntb_dev, ntb);
  343. dev_dbg(&ntb->pdev->dev,
  344. "Enabling link with max_speed %d max_width %d\n",
  345. max_speed, max_width);
  346. if (max_speed != NTB_SPEED_AUTO)
  347. dev_dbg(&ntb->pdev->dev, "ignoring max_speed %d\n", max_speed);
  348. if (max_width != NTB_WIDTH_AUTO)
  349. dev_dbg(&ntb->pdev->dev, "ignoring max_width %d\n", max_width);
  350. ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
  351. ntb_ctl &= ~(NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK);
  352. ntb_ctl |= NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;
  353. ntb_ctl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;
  354. iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
  355. return 0;
  356. }
  357. static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
  358. dma_addr_t addr, resource_size_t size)
  359. {
  360. struct intel_ntb_dev *ndev = ntb_ndev(ntb);
  361. unsigned long xlat_reg, limit_reg;
  362. resource_size_t bar_size, mw_size;
  363. void __iomem *mmio;
  364. u64 base, limit, reg_val;
  365. int bar;
  366. if (pidx != NTB_DEF_PEER_IDX)
  367. return -EINVAL;
  368. if (idx >= ndev->b2b_idx && !ndev->b2b_off)
  369. idx += 1;
  370. bar = ndev_mw_to_bar(ndev, idx);
  371. if (bar < 0)
  372. return bar;
  373. bar_size = pci_resource_len(ndev->ntb.pdev, bar);
  374. if (idx == ndev->b2b_idx)
  375. mw_size = bar_size - ndev->b2b_off;
  376. else
  377. mw_size = bar_size;
  378. /* hardware requires that addr is aligned to bar size */
  379. if (addr & (bar_size - 1))
  380. return -EINVAL;
  381. /* make sure the range fits in the usable mw size */
  382. if (size > mw_size)
  383. return -EINVAL;
  384. mmio = ndev->self_mmio;
  385. xlat_reg = ndev->xlat_reg->bar2_xlat + (idx * 0x10);
  386. limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10);
  387. base = pci_resource_start(ndev->ntb.pdev, bar);
  388. /* Set the limit if supported, if size is not mw_size */
  389. if (limit_reg && size != mw_size)
  390. limit = base + size;
  391. else
  392. limit = base + mw_size;
  393. /* set and verify setting the translation address */
  394. iowrite64(addr, mmio + xlat_reg);
  395. reg_val = ioread64(mmio + xlat_reg);
  396. if (reg_val != addr) {
  397. iowrite64(0, mmio + xlat_reg);
  398. return -EIO;
  399. }
  400. dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXBASE: %#Lx\n", bar, reg_val);
  401. /* set and verify setting the limit */
  402. iowrite64(limit, mmio + limit_reg);
  403. reg_val = ioread64(mmio + limit_reg);
  404. if (reg_val != limit) {
  405. iowrite64(base, mmio + limit_reg);
  406. iowrite64(0, mmio + xlat_reg);
  407. return -EIO;
  408. }
  409. dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXLMT: %#Lx\n", bar, reg_val);
  410. /* setup the EP */
  411. limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10) + 0x4000;
  412. base = ioread64(mmio + GEN3_EMBAR1_OFFSET + (8 * idx));
  413. base &= ~0xf;
  414. if (limit_reg && size != mw_size)
  415. limit = base + size;
  416. else
  417. limit = base + mw_size;
  418. /* set and verify setting the limit */
  419. iowrite64(limit, mmio + limit_reg);
  420. reg_val = ioread64(mmio + limit_reg);
  421. if (reg_val != limit) {
  422. iowrite64(base, mmio + limit_reg);
  423. iowrite64(0, mmio + xlat_reg);
  424. return -EIO;
  425. }
  426. dev_dbg(&ntb->pdev->dev, "BAR %d EMBARXLMT: %#Lx\n", bar, reg_val);
  427. return 0;
  428. }
  429. static int intel_ntb3_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
  430. {
  431. struct intel_ntb_dev *ndev = ntb_ndev(ntb);
  432. int bit;
  433. if (db_bits & ~ndev->db_valid_mask)
  434. return -EINVAL;
  435. while (db_bits) {
  436. bit = __ffs(db_bits);
  437. iowrite32(1, ndev->peer_mmio +
  438. ndev->peer_reg->db_bell + (bit * 4));
  439. db_bits &= db_bits - 1;
  440. }
  441. return 0;
  442. }
  443. static u64 intel_ntb3_db_read(struct ntb_dev *ntb)
  444. {
  445. struct intel_ntb_dev *ndev = ntb_ndev(ntb);
  446. return ndev_db_read(ndev,
  447. ndev->self_mmio +
  448. ndev->self_reg->db_clear);
  449. }
  450. static int intel_ntb3_db_clear(struct ntb_dev *ntb, u64 db_bits)
  451. {
  452. struct intel_ntb_dev *ndev = ntb_ndev(ntb);
  453. return ndev_db_write(ndev, db_bits,
  454. ndev->self_mmio +
  455. ndev->self_reg->db_clear);
  456. }
  457. const struct ntb_dev_ops intel_ntb3_ops = {
  458. .mw_count = intel_ntb_mw_count,
  459. .mw_get_align = intel_ntb_mw_get_align,
  460. .mw_set_trans = intel_ntb3_mw_set_trans,
  461. .peer_mw_count = intel_ntb_peer_mw_count,
  462. .peer_mw_get_addr = intel_ntb_peer_mw_get_addr,
  463. .link_is_up = intel_ntb_link_is_up,
  464. .link_enable = intel_ntb3_link_enable,
  465. .link_disable = intel_ntb_link_disable,
  466. .db_valid_mask = intel_ntb_db_valid_mask,
  467. .db_vector_count = intel_ntb_db_vector_count,
  468. .db_vector_mask = intel_ntb_db_vector_mask,
  469. .db_read = intel_ntb3_db_read,
  470. .db_clear = intel_ntb3_db_clear,
  471. .db_set_mask = intel_ntb_db_set_mask,
  472. .db_clear_mask = intel_ntb_db_clear_mask,
  473. .peer_db_addr = intel_ntb_peer_db_addr,
  474. .peer_db_set = intel_ntb3_peer_db_set,
  475. .spad_is_unsafe = intel_ntb_spad_is_unsafe,
  476. .spad_count = intel_ntb_spad_count,
  477. .spad_read = intel_ntb_spad_read,
  478. .spad_write = intel_ntb_spad_write,
  479. .peer_spad_addr = intel_ntb_peer_spad_addr,
  480. .peer_spad_read = intel_ntb_peer_spad_read,
  481. .peer_spad_write = intel_ntb_peer_spad_write,
  482. };