mic_smpt.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /*
  2. * Intel MIC Platform Software Stack (MPSS)
  3. *
  4. * Copyright(c) 2013 Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License, version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * The full GNU General Public License is included in this distribution in
  16. * the file called "COPYING".
  17. *
  18. * Intel MIC Host driver.
  19. *
  20. */
  21. #include <linux/pci.h>
  22. #include "../common/mic_dev.h"
  23. #include "mic_device.h"
  24. #include "mic_smpt.h"
  25. static inline u64 mic_system_page_mask(struct mic_device *mdev)
  26. {
  27. return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
  28. }
  29. static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
  30. {
  31. return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
  32. }
  33. static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
  34. {
  35. return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
  36. }
  37. static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
  38. {
  39. return pa & mic_system_page_mask(mdev);
  40. }
  41. static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
  42. {
  43. return ALIGN(pa - mic_system_page_mask(mdev),
  44. mdev->smpt->info.page_size);
  45. }
  46. static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
  47. {
  48. return ALIGN(pa, mdev->smpt->info.page_size);
  49. }
  50. /* Total Cumulative system memory accessible by MIC across all SMPT entries */
  51. static inline u64 mic_max_system_memory(struct mic_device *mdev)
  52. {
  53. return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
  54. }
  55. /* Maximum system memory address accessible by MIC */
  56. static inline u64 mic_max_system_addr(struct mic_device *mdev)
  57. {
  58. return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
  59. }
  60. /* Check if the DMA address is a MIC system memory address */
  61. static inline bool
  62. mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
  63. {
  64. return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
  65. }
  66. /* Populate an SMPT entry and update the reference counts. */
  67. static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
  68. int entries, struct mic_device *mdev)
  69. {
  70. struct mic_smpt_info *smpt_info = mdev->smpt;
  71. int i;
  72. for (i = spt; i < spt + entries; i++,
  73. addr += smpt_info->info.page_size) {
  74. if (!smpt_info->entry[i].ref_count &&
  75. (smpt_info->entry[i].dma_addr != addr)) {
  76. mdev->smpt_ops->set(mdev, addr, i);
  77. smpt_info->entry[i].dma_addr = addr;
  78. }
  79. smpt_info->entry[i].ref_count += ref[i - spt];
  80. }
  81. }
  82. /*
  83. * Find an available MIC address in MIC SMPT address space
  84. * for a given DMA address and size.
  85. */
  86. static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
  87. int entries, s64 *ref, size_t size)
  88. {
  89. int spt;
  90. int ae = 0;
  91. int i;
  92. unsigned long flags;
  93. dma_addr_t mic_addr = 0;
  94. dma_addr_t addr = dma_addr;
  95. struct mic_smpt_info *smpt_info = mdev->smpt;
  96. spin_lock_irqsave(&smpt_info->smpt_lock, flags);
  97. /* find existing entries */
  98. for (i = 0; i < smpt_info->info.num_reg; i++) {
  99. if (smpt_info->entry[i].dma_addr == addr) {
  100. ae++;
  101. addr += smpt_info->info.page_size;
  102. } else if (ae) /* cannot find contiguous entries */
  103. goto not_found;
  104. if (ae == entries)
  105. goto found;
  106. }
  107. /* find free entry */
  108. for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
  109. ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
  110. if (ae == entries)
  111. goto found;
  112. }
  113. not_found:
  114. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  115. return mic_addr;
  116. found:
  117. spt = i - entries + 1;
  118. mic_addr = mic_smpt_to_pa(mdev, spt);
  119. mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
  120. smpt_info->map_count++;
  121. smpt_info->ref_count += (s64)size;
  122. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  123. return mic_addr;
  124. }
  125. /*
  126. * Returns number of smpt entries needed for dma_addr to dma_addr + size
  127. * also returns the reference count array for each of those entries
  128. * and the starting smpt address
  129. */
  130. static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
  131. size_t size, s64 *ref, u64 *smpt_start)
  132. {
  133. u64 start = dma_addr;
  134. u64 end = dma_addr + size;
  135. int i = 0;
  136. while (start < end) {
  137. ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
  138. end) - start;
  139. start = mic_smpt_align_high(mdev, start + 1);
  140. }
  141. if (smpt_start)
  142. *smpt_start = mic_smpt_align_low(mdev, dma_addr);
  143. return i;
  144. }
  145. /*
  146. * mic_to_dma_addr - Converts a MIC address to a DMA address.
  147. *
  148. * @mdev: pointer to mic_device instance.
  149. * @mic_addr: MIC address.
  150. *
  151. * returns a DMA address.
  152. */
  153. static dma_addr_t
  154. mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
  155. {
  156. struct mic_smpt_info *smpt_info = mdev->smpt;
  157. int spt;
  158. dma_addr_t dma_addr;
  159. if (!mic_is_system_addr(mdev, mic_addr)) {
  160. dev_err(mdev->sdev->parent,
  161. "mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
  162. return -EINVAL;
  163. }
  164. spt = mic_sys_addr_to_smpt(mdev, mic_addr);
  165. dma_addr = smpt_info->entry[spt].dma_addr +
  166. mic_smpt_offset(mdev, mic_addr);
  167. return dma_addr;
  168. }
  169. /**
  170. * mic_map - Maps a DMA address to a MIC physical address.
  171. *
  172. * @mdev: pointer to mic_device instance.
  173. * @dma_addr: DMA address.
  174. * @size: Size of the region to be mapped.
  175. *
  176. * This API converts the DMA address provided to a DMA address understood
  177. * by MIC. Caller should check for errors by calling mic_map_error(..).
  178. *
  179. * returns DMA address as required by MIC.
  180. */
  181. dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
  182. {
  183. dma_addr_t mic_addr = 0;
  184. int num_entries;
  185. s64 *ref;
  186. u64 smpt_start;
  187. if (!size || size > mic_max_system_memory(mdev))
  188. return mic_addr;
  189. ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
  190. if (!ref)
  191. return mic_addr;
  192. num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
  193. ref, &smpt_start);
  194. /* Set the smpt table appropriately and get 16G aligned mic address */
  195. mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
  196. kfree(ref);
  197. /*
  198. * If mic_addr is zero then its an error case
  199. * since mic_addr can never be zero.
  200. * else generate mic_addr by adding the 16G offset in dma_addr
  201. */
  202. if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
  203. dev_err(mdev->sdev->parent,
  204. "mic_map failed dma_addr 0x%llx size 0x%lx\n",
  205. dma_addr, size);
  206. return mic_addr;
  207. } else {
  208. return mic_addr + mic_smpt_offset(mdev, dma_addr);
  209. }
  210. }
  211. /**
  212. * mic_unmap - Unmaps a MIC physical address.
  213. *
  214. * @mdev: pointer to mic_device instance.
  215. * @mic_addr: MIC physical address.
  216. * @size: Size of the region to be unmapped.
  217. *
  218. * This API unmaps the mappings created by mic_map(..).
  219. *
  220. * returns None.
  221. */
  222. void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
  223. {
  224. struct mic_smpt_info *smpt_info = mdev->smpt;
  225. s64 *ref;
  226. int num_smpt;
  227. int spt;
  228. int i;
  229. unsigned long flags;
  230. if (!size)
  231. return;
  232. if (!mic_is_system_addr(mdev, mic_addr)) {
  233. dev_err(mdev->sdev->parent,
  234. "invalid address: 0x%llx\n", mic_addr);
  235. return;
  236. }
  237. spt = mic_sys_addr_to_smpt(mdev, mic_addr);
  238. ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
  239. if (!ref)
  240. return;
  241. /* Get number of smpt entries to be mapped, ref count array */
  242. num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
  243. spin_lock_irqsave(&smpt_info->smpt_lock, flags);
  244. smpt_info->unmap_count++;
  245. smpt_info->ref_count -= (s64)size;
  246. for (i = spt; i < spt + num_smpt; i++) {
  247. smpt_info->entry[i].ref_count -= ref[i - spt];
  248. if (smpt_info->entry[i].ref_count < 0)
  249. dev_warn(mdev->sdev->parent,
  250. "ref count for entry %d is negative\n", i);
  251. }
  252. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  253. kfree(ref);
  254. }
  255. /**
  256. * mic_map_single - Maps a virtual address to a MIC physical address.
  257. *
  258. * @mdev: pointer to mic_device instance.
  259. * @va: Kernel direct mapped virtual address.
  260. * @size: Size of the region to be mapped.
  261. *
  262. * This API calls pci_map_single(..) for the direct mapped virtual address
  263. * and then converts the DMA address provided to a DMA address understood
  264. * by MIC. Caller should check for errors by calling mic_map_error(..).
  265. *
  266. * returns DMA address as required by MIC.
  267. */
  268. dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
  269. {
  270. dma_addr_t mic_addr = 0;
  271. struct pci_dev *pdev = container_of(mdev->sdev->parent,
  272. struct pci_dev, dev);
  273. dma_addr_t dma_addr =
  274. pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
  275. if (!pci_dma_mapping_error(pdev, dma_addr)) {
  276. mic_addr = mic_map(mdev, dma_addr, size);
  277. if (!mic_addr) {
  278. dev_err(mdev->sdev->parent,
  279. "mic_map failed dma_addr 0x%llx size 0x%lx\n",
  280. dma_addr, size);
  281. pci_unmap_single(pdev, dma_addr,
  282. size, PCI_DMA_BIDIRECTIONAL);
  283. }
  284. }
  285. return mic_addr;
  286. }
  287. /**
  288. * mic_unmap_single - Unmaps a MIC physical address.
  289. *
  290. * @mdev: pointer to mic_device instance.
  291. * @mic_addr: MIC physical address.
  292. * @size: Size of the region to be unmapped.
  293. *
  294. * This API unmaps the mappings created by mic_map_single(..).
  295. *
  296. * returns None.
  297. */
  298. void
  299. mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
  300. {
  301. struct pci_dev *pdev = container_of(mdev->sdev->parent,
  302. struct pci_dev, dev);
  303. dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
  304. mic_unmap(mdev, mic_addr, size);
  305. pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
  306. }
  307. /**
  308. * mic_smpt_init - Initialize MIC System Memory Page Tables.
  309. *
  310. * @mdev: pointer to mic_device instance.
  311. *
  312. * returns 0 for success and -errno for error.
  313. */
  314. int mic_smpt_init(struct mic_device *mdev)
  315. {
  316. int i, err = 0;
  317. dma_addr_t dma_addr;
  318. struct mic_smpt_info *smpt_info;
  319. mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
  320. if (!mdev->smpt)
  321. return -ENOMEM;
  322. smpt_info = mdev->smpt;
  323. mdev->smpt_ops->init(mdev);
  324. smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
  325. sizeof(*smpt_info->entry), GFP_KERNEL);
  326. if (!smpt_info->entry) {
  327. err = -ENOMEM;
  328. goto free_smpt;
  329. }
  330. spin_lock_init(&smpt_info->smpt_lock);
  331. for (i = 0; i < smpt_info->info.num_reg; i++) {
  332. dma_addr = i * smpt_info->info.page_size;
  333. smpt_info->entry[i].dma_addr = dma_addr;
  334. smpt_info->entry[i].ref_count = 0;
  335. mdev->smpt_ops->set(mdev, dma_addr, i);
  336. }
  337. smpt_info->ref_count = 0;
  338. smpt_info->map_count = 0;
  339. smpt_info->unmap_count = 0;
  340. return 0;
  341. free_smpt:
  342. kfree(smpt_info);
  343. return err;
  344. }
  345. /**
  346. * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
  347. *
  348. * @mdev: pointer to mic_device instance.
  349. *
  350. * returns None.
  351. */
  352. void mic_smpt_uninit(struct mic_device *mdev)
  353. {
  354. struct mic_smpt_info *smpt_info = mdev->smpt;
  355. int i;
  356. dev_dbg(mdev->sdev->parent,
  357. "nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
  358. mdev->id, smpt_info->ref_count,
  359. smpt_info->map_count, smpt_info->unmap_count);
  360. for (i = 0; i < smpt_info->info.num_reg; i++) {
  361. dev_dbg(mdev->sdev->parent,
  362. "SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
  363. i, smpt_info->entry[i].dma_addr,
  364. smpt_info->entry[i].ref_count);
  365. if (smpt_info->entry[i].ref_count)
  366. dev_warn(mdev->sdev->parent,
  367. "ref count for entry %d is not zero\n", i);
  368. }
  369. kfree(smpt_info->entry);
  370. kfree(smpt_info);
  371. }
  372. /**
  373. * mic_smpt_restore - Restore MIC System Memory Page Tables.
  374. *
  375. * @mdev: pointer to mic_device instance.
  376. *
  377. * Restore the SMPT registers to values previously stored in the
  378. * SW data structures. Some MIC steppings lose register state
  379. * across resets and this API should be called for performing
  380. * a restore operation if required.
  381. *
  382. * returns None.
  383. */
  384. void mic_smpt_restore(struct mic_device *mdev)
  385. {
  386. int i;
  387. dma_addr_t dma_addr;
  388. for (i = 0; i < mdev->smpt->info.num_reg; i++) {
  389. dma_addr = mdev->smpt->entry[i].dma_addr;
  390. mdev->smpt_ops->set(mdev, dma_addr, i);
  391. }
  392. }