hns_roce_hem.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. /*
  2. * Copyright (c) 2016 Hisilicon Limited.
  3. * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  4. *
  5. * This software is available to you under a choice of one of two
  6. * licenses. You may choose to be licensed under the terms of the GNU
  7. * General Public License (GPL) Version 2, available from the file
  8. * COPYING in the main directory of this source tree, or the
  9. * OpenIB.org BSD license below:
  10. *
  11. * Redistribution and use in source and binary forms, with or
  12. * without modification, are permitted provided that the following
  13. * conditions are met:
  14. *
  15. * - Redistributions of source code must retain the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials
  22. * provided with the distribution.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31. * SOFTWARE.
  32. */
  33. #include <linux/platform_device.h>
  34. #include "hns_roce_device.h"
  35. #include "hns_roce_hem.h"
  36. #include "hns_roce_common.h"
  37. #define DMA_ADDR_T_SHIFT 12
  38. #define BT_BA_SHIFT 32
  39. bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type)
  40. {
  41. if ((hr_dev->caps.qpc_hop_num && type == HEM_TYPE_QPC) ||
  42. (hr_dev->caps.mpt_hop_num && type == HEM_TYPE_MTPT) ||
  43. (hr_dev->caps.cqc_hop_num && type == HEM_TYPE_CQC) ||
  44. (hr_dev->caps.srqc_hop_num && type == HEM_TYPE_SRQC) ||
  45. (hr_dev->caps.cqe_hop_num && type == HEM_TYPE_CQE) ||
  46. (hr_dev->caps.mtt_hop_num && type == HEM_TYPE_MTT))
  47. return true;
  48. return false;
  49. }
  50. EXPORT_SYMBOL_GPL(hns_roce_check_whether_mhop);
  51. static bool hns_roce_check_hem_null(struct hns_roce_hem **hem, u64 start_idx,
  52. u32 bt_chunk_num, u64 hem_max_num)
  53. {
  54. u64 check_max_num = start_idx + bt_chunk_num;
  55. u64 i;
  56. for (i = start_idx; (i < check_max_num) && (i < hem_max_num); i++)
  57. if (hem[i])
  58. return false;
  59. return true;
  60. }
  61. static bool hns_roce_check_bt_null(u64 **bt, u64 start_idx, u32 bt_chunk_num)
  62. {
  63. int i;
  64. for (i = 0; i < bt_chunk_num; i++)
  65. if (bt[start_idx + i])
  66. return false;
  67. return true;
  68. }
  69. static int hns_roce_get_bt_num(u32 table_type, u32 hop_num)
  70. {
  71. if (check_whether_bt_num_3(table_type, hop_num))
  72. return 3;
  73. else if (check_whether_bt_num_2(table_type, hop_num))
  74. return 2;
  75. else if (check_whether_bt_num_1(table_type, hop_num))
  76. return 1;
  77. else
  78. return 0;
  79. }
  80. int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
  81. struct hns_roce_hem_table *table, unsigned long *obj,
  82. struct hns_roce_hem_mhop *mhop)
  83. {
  84. struct device *dev = hr_dev->dev;
  85. u32 chunk_ba_num;
  86. u32 table_idx;
  87. u32 bt_num;
  88. u32 chunk_size;
  89. switch (table->type) {
  90. case HEM_TYPE_QPC:
  91. mhop->buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz
  92. + PAGE_SHIFT);
  93. mhop->bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz
  94. + PAGE_SHIFT);
  95. mhop->ba_l0_num = hr_dev->caps.qpc_bt_num;
  96. mhop->hop_num = hr_dev->caps.qpc_hop_num;
  97. break;
  98. case HEM_TYPE_MTPT:
  99. mhop->buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz
  100. + PAGE_SHIFT);
  101. mhop->bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz
  102. + PAGE_SHIFT);
  103. mhop->ba_l0_num = hr_dev->caps.mpt_bt_num;
  104. mhop->hop_num = hr_dev->caps.mpt_hop_num;
  105. break;
  106. case HEM_TYPE_CQC:
  107. mhop->buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz
  108. + PAGE_SHIFT);
  109. mhop->bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz
  110. + PAGE_SHIFT);
  111. mhop->ba_l0_num = hr_dev->caps.cqc_bt_num;
  112. mhop->hop_num = hr_dev->caps.cqc_hop_num;
  113. break;
  114. case HEM_TYPE_SRQC:
  115. mhop->buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
  116. + PAGE_SHIFT);
  117. mhop->bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz
  118. + PAGE_SHIFT);
  119. mhop->ba_l0_num = hr_dev->caps.srqc_bt_num;
  120. mhop->hop_num = hr_dev->caps.srqc_hop_num;
  121. break;
  122. case HEM_TYPE_MTT:
  123. mhop->buf_chunk_size = 1 << (hr_dev->caps.mtt_buf_pg_sz
  124. + PAGE_SHIFT);
  125. mhop->bt_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz
  126. + PAGE_SHIFT);
  127. mhop->ba_l0_num = mhop->bt_chunk_size / 8;
  128. mhop->hop_num = hr_dev->caps.mtt_hop_num;
  129. break;
  130. case HEM_TYPE_CQE:
  131. mhop->buf_chunk_size = 1 << (hr_dev->caps.cqe_buf_pg_sz
  132. + PAGE_SHIFT);
  133. mhop->bt_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz
  134. + PAGE_SHIFT);
  135. mhop->ba_l0_num = mhop->bt_chunk_size / 8;
  136. mhop->hop_num = hr_dev->caps.cqe_hop_num;
  137. break;
  138. default:
  139. dev_err(dev, "Table %d not support multi-hop addressing!\n",
  140. table->type);
  141. return -EINVAL;
  142. }
  143. if (!obj)
  144. return 0;
  145. /*
  146. * QPC/MTPT/CQC/SRQC alloc hem for buffer pages.
  147. * MTT/CQE alloc hem for bt pages.
  148. */
  149. bt_num = hns_roce_get_bt_num(table->type, mhop->hop_num);
  150. chunk_ba_num = mhop->bt_chunk_size / 8;
  151. chunk_size = table->type < HEM_TYPE_MTT ? mhop->buf_chunk_size :
  152. mhop->bt_chunk_size;
  153. table_idx = (*obj & (table->num_obj - 1)) /
  154. (chunk_size / table->obj_size);
  155. switch (bt_num) {
  156. case 3:
  157. mhop->l2_idx = table_idx & (chunk_ba_num - 1);
  158. mhop->l1_idx = table_idx / chunk_ba_num & (chunk_ba_num - 1);
  159. mhop->l0_idx = (table_idx / chunk_ba_num) / chunk_ba_num;
  160. break;
  161. case 2:
  162. mhop->l1_idx = table_idx & (chunk_ba_num - 1);
  163. mhop->l0_idx = table_idx / chunk_ba_num;
  164. break;
  165. case 1:
  166. mhop->l0_idx = table_idx;
  167. break;
  168. default:
  169. dev_err(dev, "Table %d not support hop_num = %d!\n",
  170. table->type, mhop->hop_num);
  171. return -EINVAL;
  172. }
  173. if (mhop->l0_idx >= mhop->ba_l0_num)
  174. mhop->l0_idx %= mhop->ba_l0_num;
  175. return 0;
  176. }
  177. EXPORT_SYMBOL_GPL(hns_roce_calc_hem_mhop);
  178. static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev,
  179. int npages,
  180. unsigned long hem_alloc_size,
  181. gfp_t gfp_mask)
  182. {
  183. struct hns_roce_hem_chunk *chunk = NULL;
  184. struct hns_roce_hem *hem;
  185. struct scatterlist *mem;
  186. int order;
  187. void *buf;
  188. WARN_ON(gfp_mask & __GFP_HIGHMEM);
  189. hem = kmalloc(sizeof(*hem),
  190. gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
  191. if (!hem)
  192. return NULL;
  193. hem->refcount = 0;
  194. INIT_LIST_HEAD(&hem->chunk_list);
  195. order = get_order(hem_alloc_size);
  196. while (npages > 0) {
  197. if (!chunk) {
  198. chunk = kmalloc(sizeof(*chunk),
  199. gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
  200. if (!chunk)
  201. goto fail;
  202. sg_init_table(chunk->mem, HNS_ROCE_HEM_CHUNK_LEN);
  203. chunk->npages = 0;
  204. chunk->nsg = 0;
  205. memset(chunk->buf, 0, sizeof(chunk->buf));
  206. list_add_tail(&chunk->list, &hem->chunk_list);
  207. }
  208. while (1 << order > npages)
  209. --order;
  210. /*
  211. * Alloc memory one time. If failed, don't alloc small block
  212. * memory, directly return fail.
  213. */
  214. mem = &chunk->mem[chunk->npages];
  215. buf = dma_alloc_coherent(hr_dev->dev, PAGE_SIZE << order,
  216. &sg_dma_address(mem), gfp_mask);
  217. if (!buf)
  218. goto fail;
  219. chunk->buf[chunk->npages] = buf;
  220. sg_dma_len(mem) = PAGE_SIZE << order;
  221. ++chunk->npages;
  222. ++chunk->nsg;
  223. npages -= 1 << order;
  224. }
  225. return hem;
  226. fail:
  227. hns_roce_free_hem(hr_dev, hem);
  228. return NULL;
  229. }
  230. void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem)
  231. {
  232. struct hns_roce_hem_chunk *chunk, *tmp;
  233. int i;
  234. if (!hem)
  235. return;
  236. list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) {
  237. for (i = 0; i < chunk->npages; ++i)
  238. dma_free_coherent(hr_dev->dev,
  239. sg_dma_len(&chunk->mem[i]),
  240. chunk->buf[i],
  241. sg_dma_address(&chunk->mem[i]));
  242. kfree(chunk);
  243. }
  244. kfree(hem);
  245. }
  246. static int hns_roce_set_hem(struct hns_roce_dev *hr_dev,
  247. struct hns_roce_hem_table *table, unsigned long obj)
  248. {
  249. spinlock_t *lock = &hr_dev->bt_cmd_lock;
  250. struct device *dev = hr_dev->dev;
  251. unsigned long end = 0;
  252. unsigned long flags;
  253. struct hns_roce_hem_iter iter;
  254. void __iomem *bt_cmd;
  255. u32 bt_cmd_h_val = 0;
  256. u32 bt_cmd_val[2];
  257. u32 bt_cmd_l = 0;
  258. u64 bt_ba = 0;
  259. int ret = 0;
  260. /* Find the HEM(Hardware Entry Memory) entry */
  261. unsigned long i = (obj & (table->num_obj - 1)) /
  262. (table->table_chunk_size / table->obj_size);
  263. switch (table->type) {
  264. case HEM_TYPE_QPC:
  265. roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
  266. ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_QPC);
  267. break;
  268. case HEM_TYPE_MTPT:
  269. roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
  270. ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
  271. HEM_TYPE_MTPT);
  272. break;
  273. case HEM_TYPE_CQC:
  274. roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
  275. ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_CQC);
  276. break;
  277. case HEM_TYPE_SRQC:
  278. roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
  279. ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
  280. HEM_TYPE_SRQC);
  281. break;
  282. default:
  283. return ret;
  284. }
  285. roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M,
  286. ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S, obj);
  287. roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S, 0);
  288. roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S, 1);
  289. /* Currently iter only a chunk */
  290. for (hns_roce_hem_first(table->hem[i], &iter);
  291. !hns_roce_hem_last(&iter); hns_roce_hem_next(&iter)) {
  292. bt_ba = hns_roce_hem_addr(&iter) >> DMA_ADDR_T_SHIFT;
  293. spin_lock_irqsave(lock, flags);
  294. bt_cmd = hr_dev->reg_base + ROCEE_BT_CMD_H_REG;
  295. end = msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS) + jiffies;
  296. while (1) {
  297. if (readl(bt_cmd) >> BT_CMD_SYNC_SHIFT) {
  298. if (!(time_before(jiffies, end))) {
  299. dev_err(dev, "Write bt_cmd err,hw_sync is not zero.\n");
  300. spin_unlock_irqrestore(lock, flags);
  301. return -EBUSY;
  302. }
  303. } else {
  304. break;
  305. }
  306. mdelay(HW_SYNC_SLEEP_TIME_INTERVAL);
  307. }
  308. bt_cmd_l = (u32)bt_ba;
  309. roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M,
  310. ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S,
  311. bt_ba >> BT_BA_SHIFT);
  312. bt_cmd_val[0] = bt_cmd_l;
  313. bt_cmd_val[1] = bt_cmd_h_val;
  314. hns_roce_write64_k(bt_cmd_val,
  315. hr_dev->reg_base + ROCEE_BT_CMD_L_REG);
  316. spin_unlock_irqrestore(lock, flags);
  317. }
  318. return ret;
  319. }
  320. static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
  321. struct hns_roce_hem_table *table,
  322. unsigned long obj)
  323. {
  324. struct device *dev = hr_dev->dev;
  325. struct hns_roce_hem_mhop mhop;
  326. struct hns_roce_hem_iter iter;
  327. u32 buf_chunk_size;
  328. u32 bt_chunk_size;
  329. u32 chunk_ba_num;
  330. u32 hop_num;
  331. u32 size;
  332. u32 bt_num;
  333. u64 hem_idx;
  334. u64 bt_l1_idx = 0;
  335. u64 bt_l0_idx = 0;
  336. u64 bt_ba;
  337. unsigned long mhop_obj = obj;
  338. int bt_l1_allocated = 0;
  339. int bt_l0_allocated = 0;
  340. int step_idx;
  341. int ret;
  342. ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
  343. if (ret)
  344. return ret;
  345. buf_chunk_size = mhop.buf_chunk_size;
  346. bt_chunk_size = mhop.bt_chunk_size;
  347. hop_num = mhop.hop_num;
  348. chunk_ba_num = bt_chunk_size / 8;
  349. bt_num = hns_roce_get_bt_num(table->type, hop_num);
  350. switch (bt_num) {
  351. case 3:
  352. hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
  353. mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
  354. bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
  355. bt_l0_idx = mhop.l0_idx;
  356. break;
  357. case 2:
  358. hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
  359. bt_l0_idx = mhop.l0_idx;
  360. break;
  361. case 1:
  362. hem_idx = mhop.l0_idx;
  363. break;
  364. default:
  365. dev_err(dev, "Table %d not support hop_num = %d!\n",
  366. table->type, hop_num);
  367. return -EINVAL;
  368. }
  369. if (unlikely(hem_idx >= table->num_hem)) {
  370. dev_err(dev, "Table %d exceed hem limt idx = %llu,max = %lu!\n",
  371. table->type, hem_idx, table->num_hem);
  372. return -EINVAL;
  373. }
  374. mutex_lock(&table->mutex);
  375. if (table->hem[hem_idx]) {
  376. ++table->hem[hem_idx]->refcount;
  377. goto out;
  378. }
  379. /* alloc L1 BA's chunk */
  380. if ((check_whether_bt_num_3(table->type, hop_num) ||
  381. check_whether_bt_num_2(table->type, hop_num)) &&
  382. !table->bt_l0[bt_l0_idx]) {
  383. table->bt_l0[bt_l0_idx] = dma_alloc_coherent(dev, bt_chunk_size,
  384. &(table->bt_l0_dma_addr[bt_l0_idx]),
  385. GFP_KERNEL);
  386. if (!table->bt_l0[bt_l0_idx]) {
  387. ret = -ENOMEM;
  388. goto out;
  389. }
  390. bt_l0_allocated = 1;
  391. /* set base address to hardware */
  392. if (table->type < HEM_TYPE_MTT) {
  393. step_idx = 0;
  394. if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
  395. ret = -ENODEV;
  396. dev_err(dev, "set HEM base address to HW failed!\n");
  397. goto err_dma_alloc_l1;
  398. }
  399. }
  400. }
  401. /* alloc L2 BA's chunk */
  402. if (check_whether_bt_num_3(table->type, hop_num) &&
  403. !table->bt_l1[bt_l1_idx]) {
  404. table->bt_l1[bt_l1_idx] = dma_alloc_coherent(dev, bt_chunk_size,
  405. &(table->bt_l1_dma_addr[bt_l1_idx]),
  406. GFP_KERNEL);
  407. if (!table->bt_l1[bt_l1_idx]) {
  408. ret = -ENOMEM;
  409. goto err_dma_alloc_l1;
  410. }
  411. bt_l1_allocated = 1;
  412. *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) =
  413. table->bt_l1_dma_addr[bt_l1_idx];
  414. /* set base address to hardware */
  415. step_idx = 1;
  416. if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
  417. ret = -ENODEV;
  418. dev_err(dev, "set HEM base address to HW failed!\n");
  419. goto err_alloc_hem_buf;
  420. }
  421. }
  422. /*
  423. * alloc buffer space chunk for QPC/MTPT/CQC/SRQC.
  424. * alloc bt space chunk for MTT/CQE.
  425. */
  426. size = table->type < HEM_TYPE_MTT ? buf_chunk_size : bt_chunk_size;
  427. table->hem[hem_idx] = hns_roce_alloc_hem(hr_dev,
  428. size >> PAGE_SHIFT,
  429. size,
  430. (table->lowmem ? GFP_KERNEL :
  431. GFP_HIGHUSER) | __GFP_NOWARN);
  432. if (!table->hem[hem_idx]) {
  433. ret = -ENOMEM;
  434. goto err_alloc_hem_buf;
  435. }
  436. hns_roce_hem_first(table->hem[hem_idx], &iter);
  437. bt_ba = hns_roce_hem_addr(&iter);
  438. if (table->type < HEM_TYPE_MTT) {
  439. if (hop_num == 2) {
  440. *(table->bt_l1[bt_l1_idx] + mhop.l2_idx) = bt_ba;
  441. step_idx = 2;
  442. } else if (hop_num == 1) {
  443. *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba;
  444. step_idx = 1;
  445. } else if (hop_num == HNS_ROCE_HOP_NUM_0) {
  446. step_idx = 0;
  447. } else {
  448. ret = -EINVAL;
  449. goto err_dma_alloc_l1;
  450. }
  451. /* set HEM base address to hardware */
  452. if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
  453. ret = -ENODEV;
  454. dev_err(dev, "set HEM base address to HW failed!\n");
  455. goto err_alloc_hem_buf;
  456. }
  457. } else if (hop_num == 2) {
  458. *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba;
  459. }
  460. ++table->hem[hem_idx]->refcount;
  461. goto out;
  462. err_alloc_hem_buf:
  463. if (bt_l1_allocated) {
  464. dma_free_coherent(dev, bt_chunk_size, table->bt_l1[bt_l1_idx],
  465. table->bt_l1_dma_addr[bt_l1_idx]);
  466. table->bt_l1[bt_l1_idx] = NULL;
  467. }
  468. err_dma_alloc_l1:
  469. if (bt_l0_allocated) {
  470. dma_free_coherent(dev, bt_chunk_size, table->bt_l0[bt_l0_idx],
  471. table->bt_l0_dma_addr[bt_l0_idx]);
  472. table->bt_l0[bt_l0_idx] = NULL;
  473. }
  474. out:
  475. mutex_unlock(&table->mutex);
  476. return ret;
  477. }
  478. int hns_roce_table_get(struct hns_roce_dev *hr_dev,
  479. struct hns_roce_hem_table *table, unsigned long obj)
  480. {
  481. struct device *dev = hr_dev->dev;
  482. int ret = 0;
  483. unsigned long i;
  484. if (hns_roce_check_whether_mhop(hr_dev, table->type))
  485. return hns_roce_table_mhop_get(hr_dev, table, obj);
  486. i = (obj & (table->num_obj - 1)) / (table->table_chunk_size /
  487. table->obj_size);
  488. mutex_lock(&table->mutex);
  489. if (table->hem[i]) {
  490. ++table->hem[i]->refcount;
  491. goto out;
  492. }
  493. table->hem[i] = hns_roce_alloc_hem(hr_dev,
  494. table->table_chunk_size >> PAGE_SHIFT,
  495. table->table_chunk_size,
  496. (table->lowmem ? GFP_KERNEL :
  497. GFP_HIGHUSER) | __GFP_NOWARN);
  498. if (!table->hem[i]) {
  499. ret = -ENOMEM;
  500. goto out;
  501. }
  502. /* Set HEM base address(128K/page, pa) to Hardware */
  503. if (hns_roce_set_hem(hr_dev, table, obj)) {
  504. hns_roce_free_hem(hr_dev, table->hem[i]);
  505. table->hem[i] = NULL;
  506. ret = -ENODEV;
  507. dev_err(dev, "set HEM base address to HW failed.\n");
  508. goto out;
  509. }
  510. ++table->hem[i]->refcount;
  511. out:
  512. mutex_unlock(&table->mutex);
  513. return ret;
  514. }
  515. static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
  516. struct hns_roce_hem_table *table,
  517. unsigned long obj,
  518. int check_refcount)
  519. {
  520. struct device *dev = hr_dev->dev;
  521. struct hns_roce_hem_mhop mhop;
  522. unsigned long mhop_obj = obj;
  523. u32 bt_chunk_size;
  524. u32 chunk_ba_num;
  525. u32 hop_num;
  526. u32 start_idx;
  527. u32 bt_num;
  528. u64 hem_idx;
  529. u64 bt_l1_idx = 0;
  530. int ret;
  531. ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
  532. if (ret)
  533. return;
  534. bt_chunk_size = mhop.bt_chunk_size;
  535. hop_num = mhop.hop_num;
  536. chunk_ba_num = bt_chunk_size / 8;
  537. bt_num = hns_roce_get_bt_num(table->type, hop_num);
  538. switch (bt_num) {
  539. case 3:
  540. hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
  541. mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
  542. bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
  543. break;
  544. case 2:
  545. hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
  546. break;
  547. case 1:
  548. hem_idx = mhop.l0_idx;
  549. break;
  550. default:
  551. dev_err(dev, "Table %d not support hop_num = %d!\n",
  552. table->type, hop_num);
  553. return;
  554. }
  555. mutex_lock(&table->mutex);
  556. if (check_refcount && (--table->hem[hem_idx]->refcount > 0)) {
  557. mutex_unlock(&table->mutex);
  558. return;
  559. }
  560. if (table->type < HEM_TYPE_MTT && hop_num == 1) {
  561. if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
  562. dev_warn(dev, "Clear HEM base address failed.\n");
  563. } else if (table->type < HEM_TYPE_MTT && hop_num == 2) {
  564. if (hr_dev->hw->clear_hem(hr_dev, table, obj, 2))
  565. dev_warn(dev, "Clear HEM base address failed.\n");
  566. } else if (table->type < HEM_TYPE_MTT &&
  567. hop_num == HNS_ROCE_HOP_NUM_0) {
  568. if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
  569. dev_warn(dev, "Clear HEM base address failed.\n");
  570. }
  571. /*
  572. * free buffer space chunk for QPC/MTPT/CQC/SRQC.
  573. * free bt space chunk for MTT/CQE.
  574. */
  575. hns_roce_free_hem(hr_dev, table->hem[hem_idx]);
  576. table->hem[hem_idx] = NULL;
  577. if (check_whether_bt_num_2(table->type, hop_num)) {
  578. start_idx = mhop.l0_idx * chunk_ba_num;
  579. if (hns_roce_check_hem_null(table->hem, start_idx,
  580. chunk_ba_num, table->num_hem)) {
  581. if (table->type < HEM_TYPE_MTT &&
  582. hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
  583. dev_warn(dev, "Clear HEM base address failed.\n");
  584. dma_free_coherent(dev, bt_chunk_size,
  585. table->bt_l0[mhop.l0_idx],
  586. table->bt_l0_dma_addr[mhop.l0_idx]);
  587. table->bt_l0[mhop.l0_idx] = NULL;
  588. }
  589. } else if (check_whether_bt_num_3(table->type, hop_num)) {
  590. start_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
  591. mhop.l1_idx * chunk_ba_num;
  592. if (hns_roce_check_hem_null(table->hem, start_idx,
  593. chunk_ba_num, table->num_hem)) {
  594. if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
  595. dev_warn(dev, "Clear HEM base address failed.\n");
  596. dma_free_coherent(dev, bt_chunk_size,
  597. table->bt_l1[bt_l1_idx],
  598. table->bt_l1_dma_addr[bt_l1_idx]);
  599. table->bt_l1[bt_l1_idx] = NULL;
  600. start_idx = mhop.l0_idx * chunk_ba_num;
  601. if (hns_roce_check_bt_null(table->bt_l1, start_idx,
  602. chunk_ba_num)) {
  603. if (hr_dev->hw->clear_hem(hr_dev, table, obj,
  604. 0))
  605. dev_warn(dev, "Clear HEM base address failed.\n");
  606. dma_free_coherent(dev, bt_chunk_size,
  607. table->bt_l0[mhop.l0_idx],
  608. table->bt_l0_dma_addr[mhop.l0_idx]);
  609. table->bt_l0[mhop.l0_idx] = NULL;
  610. }
  611. }
  612. }
  613. mutex_unlock(&table->mutex);
  614. }
  615. void hns_roce_table_put(struct hns_roce_dev *hr_dev,
  616. struct hns_roce_hem_table *table, unsigned long obj)
  617. {
  618. struct device *dev = hr_dev->dev;
  619. unsigned long i;
  620. if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
  621. hns_roce_table_mhop_put(hr_dev, table, obj, 1);
  622. return;
  623. }
  624. i = (obj & (table->num_obj - 1)) /
  625. (table->table_chunk_size / table->obj_size);
  626. mutex_lock(&table->mutex);
  627. if (--table->hem[i]->refcount == 0) {
  628. /* Clear HEM base address */
  629. if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
  630. dev_warn(dev, "Clear HEM base address failed.\n");
  631. hns_roce_free_hem(hr_dev, table->hem[i]);
  632. table->hem[i] = NULL;
  633. }
  634. mutex_unlock(&table->mutex);
  635. }
  636. void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
  637. struct hns_roce_hem_table *table,
  638. unsigned long obj, dma_addr_t *dma_handle)
  639. {
  640. struct hns_roce_hem_chunk *chunk;
  641. struct hns_roce_hem_mhop mhop;
  642. struct hns_roce_hem *hem;
  643. void *addr = NULL;
  644. unsigned long mhop_obj = obj;
  645. unsigned long obj_per_chunk;
  646. unsigned long idx_offset;
  647. int offset, dma_offset;
  648. int length;
  649. int i, j;
  650. u32 hem_idx = 0;
  651. if (!table->lowmem)
  652. return NULL;
  653. mutex_lock(&table->mutex);
  654. if (!hns_roce_check_whether_mhop(hr_dev, table->type)) {
  655. obj_per_chunk = table->table_chunk_size / table->obj_size;
  656. hem = table->hem[(obj & (table->num_obj - 1)) / obj_per_chunk];
  657. idx_offset = (obj & (table->num_obj - 1)) % obj_per_chunk;
  658. dma_offset = offset = idx_offset * table->obj_size;
  659. } else {
  660. u32 seg_size = 64; /* 8 bytes per BA and 8 BA per segment */
  661. hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
  662. /* mtt mhop */
  663. i = mhop.l0_idx;
  664. j = mhop.l1_idx;
  665. if (mhop.hop_num == 2)
  666. hem_idx = i * (mhop.bt_chunk_size / 8) + j;
  667. else if (mhop.hop_num == 1 ||
  668. mhop.hop_num == HNS_ROCE_HOP_NUM_0)
  669. hem_idx = i;
  670. hem = table->hem[hem_idx];
  671. dma_offset = offset = (obj & (table->num_obj - 1)) * seg_size %
  672. mhop.bt_chunk_size;
  673. if (mhop.hop_num == 2)
  674. dma_offset = offset = 0;
  675. }
  676. if (!hem)
  677. goto out;
  678. list_for_each_entry(chunk, &hem->chunk_list, list) {
  679. for (i = 0; i < chunk->npages; ++i) {
  680. length = sg_dma_len(&chunk->mem[i]);
  681. if (dma_handle && dma_offset >= 0) {
  682. if (length > (u32)dma_offset)
  683. *dma_handle = sg_dma_address(
  684. &chunk->mem[i]) + dma_offset;
  685. dma_offset -= length;
  686. }
  687. if (length > (u32)offset) {
  688. addr = chunk->buf[i] + offset;
  689. goto out;
  690. }
  691. offset -= length;
  692. }
  693. }
  694. out:
  695. mutex_unlock(&table->mutex);
  696. return addr;
  697. }
  698. EXPORT_SYMBOL_GPL(hns_roce_table_find);
  699. int hns_roce_table_get_range(struct hns_roce_dev *hr_dev,
  700. struct hns_roce_hem_table *table,
  701. unsigned long start, unsigned long end)
  702. {
  703. struct hns_roce_hem_mhop mhop;
  704. unsigned long inc = table->table_chunk_size / table->obj_size;
  705. unsigned long i;
  706. int ret;
  707. if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
  708. hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
  709. inc = mhop.bt_chunk_size / table->obj_size;
  710. }
  711. /* Allocate MTT entry memory according to chunk(128K) */
  712. for (i = start; i <= end; i += inc) {
  713. ret = hns_roce_table_get(hr_dev, table, i);
  714. if (ret)
  715. goto fail;
  716. }
  717. return 0;
  718. fail:
  719. while (i > start) {
  720. i -= inc;
  721. hns_roce_table_put(hr_dev, table, i);
  722. }
  723. return ret;
  724. }
  725. void hns_roce_table_put_range(struct hns_roce_dev *hr_dev,
  726. struct hns_roce_hem_table *table,
  727. unsigned long start, unsigned long end)
  728. {
  729. struct hns_roce_hem_mhop mhop;
  730. unsigned long inc = table->table_chunk_size / table->obj_size;
  731. unsigned long i;
  732. if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
  733. hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
  734. inc = mhop.bt_chunk_size / table->obj_size;
  735. }
  736. for (i = start; i <= end; i += inc)
  737. hns_roce_table_put(hr_dev, table, i);
  738. }
  739. int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
  740. struct hns_roce_hem_table *table, u32 type,
  741. unsigned long obj_size, unsigned long nobj,
  742. int use_lowmem)
  743. {
  744. struct device *dev = hr_dev->dev;
  745. unsigned long obj_per_chunk;
  746. unsigned long num_hem;
  747. if (!hns_roce_check_whether_mhop(hr_dev, type)) {
  748. table->table_chunk_size = hr_dev->caps.chunk_sz;
  749. obj_per_chunk = table->table_chunk_size / obj_size;
  750. num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
  751. table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
  752. if (!table->hem)
  753. return -ENOMEM;
  754. } else {
  755. unsigned long buf_chunk_size;
  756. unsigned long bt_chunk_size;
  757. unsigned long bt_chunk_num;
  758. unsigned long num_bt_l0 = 0;
  759. u32 hop_num;
  760. switch (type) {
  761. case HEM_TYPE_QPC:
  762. buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz
  763. + PAGE_SHIFT);
  764. bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz
  765. + PAGE_SHIFT);
  766. num_bt_l0 = hr_dev->caps.qpc_bt_num;
  767. hop_num = hr_dev->caps.qpc_hop_num;
  768. break;
  769. case HEM_TYPE_MTPT:
  770. buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz
  771. + PAGE_SHIFT);
  772. bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz
  773. + PAGE_SHIFT);
  774. num_bt_l0 = hr_dev->caps.mpt_bt_num;
  775. hop_num = hr_dev->caps.mpt_hop_num;
  776. break;
  777. case HEM_TYPE_CQC:
  778. buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz
  779. + PAGE_SHIFT);
  780. bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz
  781. + PAGE_SHIFT);
  782. num_bt_l0 = hr_dev->caps.cqc_bt_num;
  783. hop_num = hr_dev->caps.cqc_hop_num;
  784. break;
  785. case HEM_TYPE_SRQC:
  786. buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
  787. + PAGE_SHIFT);
  788. bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz
  789. + PAGE_SHIFT);
  790. num_bt_l0 = hr_dev->caps.srqc_bt_num;
  791. hop_num = hr_dev->caps.srqc_hop_num;
  792. break;
  793. case HEM_TYPE_MTT:
  794. buf_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz
  795. + PAGE_SHIFT);
  796. bt_chunk_size = buf_chunk_size;
  797. hop_num = hr_dev->caps.mtt_hop_num;
  798. break;
  799. case HEM_TYPE_CQE:
  800. buf_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz
  801. + PAGE_SHIFT);
  802. bt_chunk_size = buf_chunk_size;
  803. hop_num = hr_dev->caps.cqe_hop_num;
  804. break;
  805. default:
  806. dev_err(dev,
  807. "Table %d not support to init hem table here!\n",
  808. type);
  809. return -EINVAL;
  810. }
  811. obj_per_chunk = buf_chunk_size / obj_size;
  812. num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
  813. bt_chunk_num = bt_chunk_size / 8;
  814. if (type >= HEM_TYPE_MTT)
  815. num_bt_l0 = bt_chunk_num;
  816. table->hem = kcalloc(num_hem, sizeof(*table->hem),
  817. GFP_KERNEL);
  818. if (!table->hem)
  819. goto err_kcalloc_hem_buf;
  820. if (check_whether_bt_num_3(type, hop_num)) {
  821. unsigned long num_bt_l1;
  822. num_bt_l1 = (num_hem + bt_chunk_num - 1) /
  823. bt_chunk_num;
  824. table->bt_l1 = kcalloc(num_bt_l1,
  825. sizeof(*table->bt_l1),
  826. GFP_KERNEL);
  827. if (!table->bt_l1)
  828. goto err_kcalloc_bt_l1;
  829. table->bt_l1_dma_addr = kcalloc(num_bt_l1,
  830. sizeof(*table->bt_l1_dma_addr),
  831. GFP_KERNEL);
  832. if (!table->bt_l1_dma_addr)
  833. goto err_kcalloc_l1_dma;
  834. }
  835. if (check_whether_bt_num_2(type, hop_num) ||
  836. check_whether_bt_num_3(type, hop_num)) {
  837. table->bt_l0 = kcalloc(num_bt_l0, sizeof(*table->bt_l0),
  838. GFP_KERNEL);
  839. if (!table->bt_l0)
  840. goto err_kcalloc_bt_l0;
  841. table->bt_l0_dma_addr = kcalloc(num_bt_l0,
  842. sizeof(*table->bt_l0_dma_addr),
  843. GFP_KERNEL);
  844. if (!table->bt_l0_dma_addr)
  845. goto err_kcalloc_l0_dma;
  846. }
  847. }
  848. table->type = type;
  849. table->num_hem = num_hem;
  850. table->num_obj = nobj;
  851. table->obj_size = obj_size;
  852. table->lowmem = use_lowmem;
  853. mutex_init(&table->mutex);
  854. return 0;
  855. err_kcalloc_l0_dma:
  856. kfree(table->bt_l0);
  857. table->bt_l0 = NULL;
  858. err_kcalloc_bt_l0:
  859. kfree(table->bt_l1_dma_addr);
  860. table->bt_l1_dma_addr = NULL;
  861. err_kcalloc_l1_dma:
  862. kfree(table->bt_l1);
  863. table->bt_l1 = NULL;
  864. err_kcalloc_bt_l1:
  865. kfree(table->hem);
  866. table->hem = NULL;
  867. err_kcalloc_hem_buf:
  868. return -ENOMEM;
  869. }
  870. static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev,
  871. struct hns_roce_hem_table *table)
  872. {
  873. struct hns_roce_hem_mhop mhop;
  874. u32 buf_chunk_size;
  875. int i;
  876. u64 obj;
  877. hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
  878. buf_chunk_size = table->type < HEM_TYPE_MTT ? mhop.buf_chunk_size :
  879. mhop.bt_chunk_size;
  880. for (i = 0; i < table->num_hem; ++i) {
  881. obj = i * buf_chunk_size / table->obj_size;
  882. if (table->hem[i])
  883. hns_roce_table_mhop_put(hr_dev, table, obj, 0);
  884. }
  885. kfree(table->hem);
  886. table->hem = NULL;
  887. kfree(table->bt_l1);
  888. table->bt_l1 = NULL;
  889. kfree(table->bt_l1_dma_addr);
  890. table->bt_l1_dma_addr = NULL;
  891. kfree(table->bt_l0);
  892. table->bt_l0 = NULL;
  893. kfree(table->bt_l0_dma_addr);
  894. table->bt_l0_dma_addr = NULL;
  895. }
  896. void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
  897. struct hns_roce_hem_table *table)
  898. {
  899. struct device *dev = hr_dev->dev;
  900. unsigned long i;
  901. if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
  902. hns_roce_cleanup_mhop_hem_table(hr_dev, table);
  903. return;
  904. }
  905. for (i = 0; i < table->num_hem; ++i)
  906. if (table->hem[i]) {
  907. if (hr_dev->hw->clear_hem(hr_dev, table,
  908. i * table->table_chunk_size / table->obj_size, 0))
  909. dev_err(dev, "Clear HEM base address failed.\n");
  910. hns_roce_free_hem(hr_dev, table->hem[i]);
  911. }
  912. kfree(table->hem);
  913. }
  914. void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev)
  915. {
  916. hns_roce_cleanup_hem_table(hr_dev, &hr_dev->cq_table.table);
  917. if (hr_dev->caps.trrl_entry_sz)
  918. hns_roce_cleanup_hem_table(hr_dev,
  919. &hr_dev->qp_table.trrl_table);
  920. hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.irrl_table);
  921. hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.qp_table);
  922. hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table);
  923. if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
  924. hns_roce_cleanup_hem_table(hr_dev,
  925. &hr_dev->mr_table.mtt_cqe_table);
  926. hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table);
  927. }