hinic_hw_api_cmd.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. /*
  2. * Huawei HiNIC PCI Express Linux driver
  3. * Copyright(c) 2017 Huawei Technologies Co., Ltd
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * for more details.
  13. *
  14. */
  15. #include <linux/kernel.h>
  16. #include <linux/types.h>
  17. #include <linux/errno.h>
  18. #include <linux/pci.h>
  19. #include <linux/device.h>
  20. #include <linux/slab.h>
  21. #include <linux/dma-mapping.h>
  22. #include <linux/bitops.h>
  23. #include <linux/err.h>
  24. #include <linux/jiffies.h>
  25. #include <linux/delay.h>
  26. #include <linux/log2.h>
  27. #include <linux/semaphore.h>
  28. #include <asm/byteorder.h>
  29. #include <asm/barrier.h>
  30. #include "hinic_hw_csr.h"
  31. #include "hinic_hw_if.h"
  32. #include "hinic_hw_api_cmd.h"
  33. #define API_CHAIN_NUM_CELLS 32
  34. #define API_CMD_CELL_SIZE_SHIFT 6
  35. #define API_CMD_CELL_SIZE_MIN (BIT(API_CMD_CELL_SIZE_SHIFT))
  36. #define API_CMD_CELL_SIZE(cell_size) \
  37. (((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \
  38. (1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN)
  39. #define API_CMD_CELL_SIZE_VAL(size) \
  40. ilog2((size) >> API_CMD_CELL_SIZE_SHIFT)
  41. #define API_CMD_BUF_SIZE 2048
  42. /* Sizes of the members in hinic_api_cmd_cell */
  43. #define API_CMD_CELL_DESC_SIZE 8
  44. #define API_CMD_CELL_DATA_ADDR_SIZE 8
  45. #define API_CMD_CELL_ALIGNMENT 8
  46. #define API_CMD_TIMEOUT 1000
  47. #define MASKED_IDX(chain, idx) ((idx) & ((chain)->num_cells - 1))
  48. #define SIZE_8BYTES(size) (ALIGN((size), 8) >> 3)
  49. #define SIZE_4BYTES(size) (ALIGN((size), 4) >> 2)
  50. #define RD_DMA_ATTR_DEFAULT 0
  51. #define WR_DMA_ATTR_DEFAULT 0
  52. enum api_cmd_data_format {
  53. SGE_DATA = 1, /* cell data is passed by hw address */
  54. };
  55. enum api_cmd_type {
  56. API_CMD_WRITE = 0,
  57. };
  58. enum api_cmd_bypass {
  59. NO_BYPASS = 0,
  60. BYPASS = 1,
  61. };
  62. enum api_cmd_xor_chk_level {
  63. XOR_CHK_DIS = 0,
  64. XOR_CHK_ALL = 3,
  65. };
  66. static u8 xor_chksum_set(void *data)
  67. {
  68. int idx;
  69. u8 *val, checksum = 0;
  70. val = data;
  71. for (idx = 0; idx < 7; idx++)
  72. checksum ^= val[idx];
  73. return checksum;
  74. }
  75. static void set_prod_idx(struct hinic_api_cmd_chain *chain)
  76. {
  77. enum hinic_api_cmd_chain_type chain_type = chain->chain_type;
  78. struct hinic_hwif *hwif = chain->hwif;
  79. u32 addr, prod_idx;
  80. addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain_type);
  81. prod_idx = hinic_hwif_read_reg(hwif, addr);
  82. prod_idx = HINIC_API_CMD_PI_CLEAR(prod_idx, IDX);
  83. prod_idx |= HINIC_API_CMD_PI_SET(chain->prod_idx, IDX);
  84. hinic_hwif_write_reg(hwif, addr, prod_idx);
  85. }
  86. static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain)
  87. {
  88. u32 addr, val;
  89. addr = HINIC_CSR_API_CMD_STATUS_ADDR(chain->chain_type);
  90. val = hinic_hwif_read_reg(chain->hwif, addr);
  91. return HINIC_API_CMD_STATUS_GET(val, CONS_IDX);
  92. }
  93. /**
  94. * chain_busy - check if the chain is still processing last requests
  95. * @chain: chain to check
  96. *
  97. * Return 0 - Success, negative - Failure
  98. **/
  99. static int chain_busy(struct hinic_api_cmd_chain *chain)
  100. {
  101. struct hinic_hwif *hwif = chain->hwif;
  102. struct pci_dev *pdev = hwif->pdev;
  103. u32 prod_idx;
  104. switch (chain->chain_type) {
  105. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  106. chain->cons_idx = get_hw_cons_idx(chain);
  107. prod_idx = chain->prod_idx;
  108. /* check for a space for a new command */
  109. if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) {
  110. dev_err(&pdev->dev, "API CMD chain %d is busy\n",
  111. chain->chain_type);
  112. return -EBUSY;
  113. }
  114. break;
  115. default:
  116. dev_err(&pdev->dev, "Unknown API CMD Chain type\n");
  117. break;
  118. }
  119. return 0;
  120. }
  121. /**
  122. * get_cell_data_size - get the data size of a specific cell type
  123. * @type: chain type
  124. *
  125. * Return the data(Desc + Address) size in the cell
  126. **/
  127. static u8 get_cell_data_size(enum hinic_api_cmd_chain_type type)
  128. {
  129. u8 cell_data_size = 0;
  130. switch (type) {
  131. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  132. cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE +
  133. API_CMD_CELL_DATA_ADDR_SIZE,
  134. API_CMD_CELL_ALIGNMENT);
  135. break;
  136. default:
  137. break;
  138. }
  139. return cell_data_size;
  140. }
  141. /**
  142. * prepare_cell_ctrl - prepare the ctrl of the cell for the command
  143. * @cell_ctrl: the control of the cell to set the control value into it
  144. * @data_size: the size of the data in the cell
  145. **/
  146. static void prepare_cell_ctrl(u64 *cell_ctrl, u16 data_size)
  147. {
  148. u8 chksum;
  149. u64 ctrl;
  150. ctrl = HINIC_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(data_size), DATA_SZ) |
  151. HINIC_API_CMD_CELL_CTRL_SET(RD_DMA_ATTR_DEFAULT, RD_DMA_ATTR) |
  152. HINIC_API_CMD_CELL_CTRL_SET(WR_DMA_ATTR_DEFAULT, WR_DMA_ATTR);
  153. chksum = xor_chksum_set(&ctrl);
  154. ctrl |= HINIC_API_CMD_CELL_CTRL_SET(chksum, XOR_CHKSUM);
  155. /* The data in the HW should be in Big Endian Format */
  156. *cell_ctrl = cpu_to_be64(ctrl);
  157. }
  158. /**
  159. * prepare_api_cmd - prepare API CMD command
  160. * @chain: chain for the command
  161. * @dest: destination node on the card that will receive the command
  162. * @cmd: command data
  163. * @cmd_size: the command size
  164. **/
  165. static void prepare_api_cmd(struct hinic_api_cmd_chain *chain,
  166. enum hinic_node_id dest,
  167. void *cmd, u16 cmd_size)
  168. {
  169. struct hinic_api_cmd_cell *cell = chain->curr_node;
  170. struct hinic_api_cmd_cell_ctxt *cell_ctxt;
  171. struct hinic_hwif *hwif = chain->hwif;
  172. struct pci_dev *pdev = hwif->pdev;
  173. cell_ctxt = &chain->cell_ctxt[chain->prod_idx];
  174. switch (chain->chain_type) {
  175. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  176. cell->desc = HINIC_API_CMD_DESC_SET(SGE_DATA, API_TYPE) |
  177. HINIC_API_CMD_DESC_SET(API_CMD_WRITE, RD_WR) |
  178. HINIC_API_CMD_DESC_SET(NO_BYPASS, MGMT_BYPASS);
  179. break;
  180. default:
  181. dev_err(&pdev->dev, "unknown Chain type\n");
  182. return;
  183. }
  184. cell->desc |= HINIC_API_CMD_DESC_SET(dest, DEST) |
  185. HINIC_API_CMD_DESC_SET(SIZE_4BYTES(cmd_size), SIZE);
  186. cell->desc |= HINIC_API_CMD_DESC_SET(xor_chksum_set(&cell->desc),
  187. XOR_CHKSUM);
  188. /* The data in the HW should be in Big Endian Format */
  189. cell->desc = cpu_to_be64(cell->desc);
  190. memcpy(cell_ctxt->api_cmd_vaddr, cmd, cmd_size);
  191. }
  192. /**
  193. * prepare_cell - prepare cell ctrl and cmd in the current cell
  194. * @chain: chain for the command
  195. * @dest: destination node on the card that will receive the command
  196. * @cmd: command data
  197. * @cmd_size: the command size
  198. *
  199. * Return 0 - Success, negative - Failure
  200. **/
  201. static void prepare_cell(struct hinic_api_cmd_chain *chain,
  202. enum hinic_node_id dest,
  203. void *cmd, u16 cmd_size)
  204. {
  205. struct hinic_api_cmd_cell *curr_node = chain->curr_node;
  206. u16 data_size = get_cell_data_size(chain->chain_type);
  207. prepare_cell_ctrl(&curr_node->ctrl, data_size);
  208. prepare_api_cmd(chain, dest, cmd, cmd_size);
  209. }
  210. static inline void cmd_chain_prod_idx_inc(struct hinic_api_cmd_chain *chain)
  211. {
  212. chain->prod_idx = MASKED_IDX(chain, chain->prod_idx + 1);
  213. }
  214. /**
  215. * api_cmd_status_update - update the status in the chain struct
  216. * @chain: chain to update
  217. **/
  218. static void api_cmd_status_update(struct hinic_api_cmd_chain *chain)
  219. {
  220. enum hinic_api_cmd_chain_type chain_type;
  221. struct hinic_api_cmd_status *wb_status;
  222. struct hinic_hwif *hwif = chain->hwif;
  223. struct pci_dev *pdev = hwif->pdev;
  224. u64 status_header;
  225. u32 status;
  226. wb_status = chain->wb_status;
  227. status_header = be64_to_cpu(wb_status->header);
  228. status = be32_to_cpu(wb_status->status);
  229. if (HINIC_API_CMD_STATUS_GET(status, CHKSUM_ERR)) {
  230. dev_err(&pdev->dev, "API CMD status: Xor check error\n");
  231. return;
  232. }
  233. chain_type = HINIC_API_CMD_STATUS_HEADER_GET(status_header, CHAIN_ID);
  234. if (chain_type >= HINIC_API_CMD_MAX) {
  235. dev_err(&pdev->dev, "unknown API CMD Chain %d\n", chain_type);
  236. return;
  237. }
  238. chain->cons_idx = HINIC_API_CMD_STATUS_GET(status, CONS_IDX);
  239. }
  240. /**
  241. * wait_for_status_poll - wait for write to api cmd command to complete
  242. * @chain: the chain of the command
  243. *
  244. * Return 0 - Success, negative - Failure
  245. **/
  246. static int wait_for_status_poll(struct hinic_api_cmd_chain *chain)
  247. {
  248. int err = -ETIMEDOUT;
  249. unsigned long end;
  250. end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);
  251. do {
  252. api_cmd_status_update(chain);
  253. /* wait for CI to be updated - sign for completion */
  254. if (chain->cons_idx == chain->prod_idx) {
  255. err = 0;
  256. break;
  257. }
  258. msleep(20);
  259. } while (time_before(jiffies, end));
  260. return err;
  261. }
  262. /**
  263. * wait_for_api_cmd_completion - wait for command to complete
  264. * @chain: chain for the command
  265. *
  266. * Return 0 - Success, negative - Failure
  267. **/
  268. static int wait_for_api_cmd_completion(struct hinic_api_cmd_chain *chain)
  269. {
  270. struct hinic_hwif *hwif = chain->hwif;
  271. struct pci_dev *pdev = hwif->pdev;
  272. int err;
  273. switch (chain->chain_type) {
  274. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  275. err = wait_for_status_poll(chain);
  276. if (err) {
  277. dev_err(&pdev->dev, "API CMD Poll status timeout\n");
  278. break;
  279. }
  280. break;
  281. default:
  282. dev_err(&pdev->dev, "unknown API CMD Chain type\n");
  283. err = -EINVAL;
  284. break;
  285. }
  286. return err;
  287. }
  288. /**
  289. * api_cmd - API CMD command
  290. * @chain: chain for the command
  291. * @dest: destination node on the card that will receive the command
  292. * @cmd: command data
  293. * @size: the command size
  294. *
  295. * Return 0 - Success, negative - Failure
  296. **/
  297. static int api_cmd(struct hinic_api_cmd_chain *chain,
  298. enum hinic_node_id dest, u8 *cmd, u16 cmd_size)
  299. {
  300. struct hinic_api_cmd_cell_ctxt *ctxt;
  301. int err;
  302. down(&chain->sem);
  303. if (chain_busy(chain)) {
  304. up(&chain->sem);
  305. return -EBUSY;
  306. }
  307. prepare_cell(chain, dest, cmd, cmd_size);
  308. cmd_chain_prod_idx_inc(chain);
  309. wmb(); /* inc pi before issue the command */
  310. set_prod_idx(chain); /* issue the command */
  311. ctxt = &chain->cell_ctxt[chain->prod_idx];
  312. chain->curr_node = ctxt->cell_vaddr;
  313. err = wait_for_api_cmd_completion(chain);
  314. up(&chain->sem);
  315. return err;
  316. }
  317. /**
  318. * hinic_api_cmd_write - Write API CMD command
  319. * @chain: chain for write command
  320. * @dest: destination node on the card that will receive the command
  321. * @cmd: command data
  322. * @size: the command size
  323. *
  324. * Return 0 - Success, negative - Failure
  325. **/
  326. int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain,
  327. enum hinic_node_id dest, u8 *cmd, u16 size)
  328. {
  329. /* Verify the chain type */
  330. if (chain->chain_type == HINIC_API_CMD_WRITE_TO_MGMT_CPU)
  331. return api_cmd(chain, dest, cmd, size);
  332. return -EINVAL;
  333. }
  334. /**
  335. * api_cmd_hw_restart - restart the chain in the HW
  336. * @chain: the API CMD specific chain to restart
  337. *
  338. * Return 0 - Success, negative - Failure
  339. **/
  340. static int api_cmd_hw_restart(struct hinic_api_cmd_chain *chain)
  341. {
  342. struct hinic_hwif *hwif = chain->hwif;
  343. int err = -ETIMEDOUT;
  344. unsigned long end;
  345. u32 reg_addr, val;
  346. /* Read Modify Write */
  347. reg_addr = HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(chain->chain_type);
  348. val = hinic_hwif_read_reg(hwif, reg_addr);
  349. val = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART);
  350. val |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART);
  351. hinic_hwif_write_reg(hwif, reg_addr, val);
  352. end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);
  353. do {
  354. val = hinic_hwif_read_reg(hwif, reg_addr);
  355. if (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) {
  356. err = 0;
  357. break;
  358. }
  359. msleep(20);
  360. } while (time_before(jiffies, end));
  361. return err;
  362. }
  363. /**
  364. * api_cmd_ctrl_init - set the control register of a chain
  365. * @chain: the API CMD specific chain to set control register for
  366. **/
  367. static void api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain)
  368. {
  369. struct hinic_hwif *hwif = chain->hwif;
  370. u32 addr, ctrl;
  371. u16 cell_size;
  372. /* Read Modify Write */
  373. addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);
  374. cell_size = API_CMD_CELL_SIZE_VAL(chain->cell_size);
  375. ctrl = hinic_hwif_read_reg(hwif, addr);
  376. ctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) &
  377. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) &
  378. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) &
  379. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) &
  380. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);
  381. ctrl |= HINIC_API_CMD_CHAIN_CTRL_SET(1, XOR_ERR) |
  382. HINIC_API_CMD_CHAIN_CTRL_SET(XOR_CHK_ALL, XOR_CHK_EN) |
  383. HINIC_API_CMD_CHAIN_CTRL_SET(cell_size, CELL_SIZE);
  384. hinic_hwif_write_reg(hwif, addr, ctrl);
  385. }
  386. /**
  387. * api_cmd_set_status_addr - set the status address of a chain in the HW
  388. * @chain: the API CMD specific chain to set in HW status address for
  389. **/
  390. static void api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain)
  391. {
  392. struct hinic_hwif *hwif = chain->hwif;
  393. u32 addr, val;
  394. addr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type);
  395. val = upper_32_bits(chain->wb_status_paddr);
  396. hinic_hwif_write_reg(hwif, addr, val);
  397. addr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type);
  398. val = lower_32_bits(chain->wb_status_paddr);
  399. hinic_hwif_write_reg(hwif, addr, val);
  400. }
  401. /**
  402. * api_cmd_set_num_cells - set the number cells of a chain in the HW
  403. * @chain: the API CMD specific chain to set in HW the number of cells for
  404. **/
  405. static void api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain)
  406. {
  407. struct hinic_hwif *hwif = chain->hwif;
  408. u32 addr, val;
  409. addr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type);
  410. val = chain->num_cells;
  411. hinic_hwif_write_reg(hwif, addr, val);
  412. }
  413. /**
  414. * api_cmd_head_init - set the head of a chain in the HW
  415. * @chain: the API CMD specific chain to set in HW the head for
  416. **/
  417. static void api_cmd_head_init(struct hinic_api_cmd_chain *chain)
  418. {
  419. struct hinic_hwif *hwif = chain->hwif;
  420. u32 addr, val;
  421. addr = HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type);
  422. val = upper_32_bits(chain->head_cell_paddr);
  423. hinic_hwif_write_reg(hwif, addr, val);
  424. addr = HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type);
  425. val = lower_32_bits(chain->head_cell_paddr);
  426. hinic_hwif_write_reg(hwif, addr, val);
  427. }
  428. /**
  429. * api_cmd_chain_hw_clean - clean the HW
  430. * @chain: the API CMD specific chain
  431. **/
  432. static void api_cmd_chain_hw_clean(struct hinic_api_cmd_chain *chain)
  433. {
  434. struct hinic_hwif *hwif = chain->hwif;
  435. u32 addr, ctrl;
  436. addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);
  437. ctrl = hinic_hwif_read_reg(hwif, addr);
  438. ctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) &
  439. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) &
  440. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) &
  441. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) &
  442. HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);
  443. hinic_hwif_write_reg(hwif, addr, ctrl);
  444. }
  445. /**
  446. * api_cmd_chain_hw_init - initialize the chain in the HW
  447. * @chain: the API CMD specific chain to initialize in HW
  448. *
  449. * Return 0 - Success, negative - Failure
  450. **/
  451. static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain)
  452. {
  453. struct hinic_hwif *hwif = chain->hwif;
  454. struct pci_dev *pdev = hwif->pdev;
  455. int err;
  456. api_cmd_chain_hw_clean(chain);
  457. api_cmd_set_status_addr(chain);
  458. err = api_cmd_hw_restart(chain);
  459. if (err) {
  460. dev_err(&pdev->dev, "Failed to restart API CMD HW\n");
  461. return err;
  462. }
  463. api_cmd_ctrl_init(chain);
  464. api_cmd_set_num_cells(chain);
  465. api_cmd_head_init(chain);
  466. return 0;
  467. }
  468. /**
  469. * free_cmd_buf - free the dma buffer of API CMD command
  470. * @chain: the API CMD specific chain of the cmd
  471. * @cell_idx: the cell index of the cmd
  472. **/
  473. static void free_cmd_buf(struct hinic_api_cmd_chain *chain, int cell_idx)
  474. {
  475. struct hinic_api_cmd_cell_ctxt *cell_ctxt;
  476. struct hinic_hwif *hwif = chain->hwif;
  477. struct pci_dev *pdev = hwif->pdev;
  478. cell_ctxt = &chain->cell_ctxt[cell_idx];
  479. dma_free_coherent(&pdev->dev, API_CMD_BUF_SIZE,
  480. cell_ctxt->api_cmd_vaddr,
  481. cell_ctxt->api_cmd_paddr);
  482. }
  483. /**
  484. * alloc_cmd_buf - allocate a dma buffer for API CMD command
  485. * @chain: the API CMD specific chain for the cmd
  486. * @cell: the cell in the HW for the cmd
  487. * @cell_idx: the index of the cell
  488. *
  489. * Return 0 - Success, negative - Failure
  490. **/
  491. static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain,
  492. struct hinic_api_cmd_cell *cell, int cell_idx)
  493. {
  494. struct hinic_api_cmd_cell_ctxt *cell_ctxt;
  495. struct hinic_hwif *hwif = chain->hwif;
  496. struct pci_dev *pdev = hwif->pdev;
  497. dma_addr_t cmd_paddr;
  498. u8 *cmd_vaddr;
  499. int err = 0;
  500. cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
  501. &cmd_paddr, GFP_KERNEL);
  502. if (!cmd_vaddr) {
  503. dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n");
  504. return -ENOMEM;
  505. }
  506. cell_ctxt = &chain->cell_ctxt[cell_idx];
  507. cell_ctxt->api_cmd_vaddr = cmd_vaddr;
  508. cell_ctxt->api_cmd_paddr = cmd_paddr;
  509. /* set the cmd DMA address in the cell */
  510. switch (chain->chain_type) {
  511. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  512. /* The data in the HW should be in Big Endian Format */
  513. cell->write.hw_cmd_paddr = cpu_to_be64(cmd_paddr);
  514. break;
  515. default:
  516. dev_err(&pdev->dev, "Unsupported API CMD chain type\n");
  517. free_cmd_buf(chain, cell_idx);
  518. err = -EINVAL;
  519. break;
  520. }
  521. return err;
  522. }
  523. /**
  524. * api_cmd_create_cell - create API CMD cell for specific chain
  525. * @chain: the API CMD specific chain to create its cell
  526. * @cell_idx: the index of the cell to create
  527. * @pre_node: previous cell
  528. * @node_vaddr: the returned virt addr of the cell
  529. *
  530. * Return 0 - Success, negative - Failure
  531. **/
  532. static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain,
  533. int cell_idx,
  534. struct hinic_api_cmd_cell *pre_node,
  535. struct hinic_api_cmd_cell **node_vaddr)
  536. {
  537. struct hinic_api_cmd_cell_ctxt *cell_ctxt;
  538. struct hinic_hwif *hwif = chain->hwif;
  539. struct pci_dev *pdev = hwif->pdev;
  540. struct hinic_api_cmd_cell *node;
  541. dma_addr_t node_paddr;
  542. int err;
  543. node = dma_zalloc_coherent(&pdev->dev, chain->cell_size,
  544. &node_paddr, GFP_KERNEL);
  545. if (!node) {
  546. dev_err(&pdev->dev, "Failed to allocate dma API CMD cell\n");
  547. return -ENOMEM;
  548. }
  549. node->read.hw_wb_resp_paddr = 0;
  550. cell_ctxt = &chain->cell_ctxt[cell_idx];
  551. cell_ctxt->cell_vaddr = node;
  552. cell_ctxt->cell_paddr = node_paddr;
  553. if (!pre_node) {
  554. chain->head_cell_paddr = node_paddr;
  555. chain->head_node = node;
  556. } else {
  557. /* The data in the HW should be in Big Endian Format */
  558. pre_node->next_cell_paddr = cpu_to_be64(node_paddr);
  559. }
  560. switch (chain->chain_type) {
  561. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  562. err = alloc_cmd_buf(chain, node, cell_idx);
  563. if (err) {
  564. dev_err(&pdev->dev, "Failed to allocate cmd buffer\n");
  565. goto err_alloc_cmd_buf;
  566. }
  567. break;
  568. default:
  569. dev_err(&pdev->dev, "Unsupported API CMD chain type\n");
  570. err = -EINVAL;
  571. goto err_alloc_cmd_buf;
  572. }
  573. *node_vaddr = node;
  574. return 0;
  575. err_alloc_cmd_buf:
  576. dma_free_coherent(&pdev->dev, chain->cell_size, node, node_paddr);
  577. return err;
  578. }
  579. /**
  580. * api_cmd_destroy_cell - destroy API CMD cell of specific chain
  581. * @chain: the API CMD specific chain to destroy its cell
  582. * @cell_idx: the cell to destroy
  583. **/
  584. static void api_cmd_destroy_cell(struct hinic_api_cmd_chain *chain,
  585. int cell_idx)
  586. {
  587. struct hinic_api_cmd_cell_ctxt *cell_ctxt;
  588. struct hinic_hwif *hwif = chain->hwif;
  589. struct pci_dev *pdev = hwif->pdev;
  590. struct hinic_api_cmd_cell *node;
  591. dma_addr_t node_paddr;
  592. size_t node_size;
  593. cell_ctxt = &chain->cell_ctxt[cell_idx];
  594. node = cell_ctxt->cell_vaddr;
  595. node_paddr = cell_ctxt->cell_paddr;
  596. node_size = chain->cell_size;
  597. if (cell_ctxt->api_cmd_vaddr) {
  598. switch (chain->chain_type) {
  599. case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
  600. free_cmd_buf(chain, cell_idx);
  601. break;
  602. default:
  603. dev_err(&pdev->dev, "Unsupported API CMD chain type\n");
  604. break;
  605. }
  606. dma_free_coherent(&pdev->dev, node_size, node,
  607. node_paddr);
  608. }
  609. }
  610. /**
  611. * api_cmd_destroy_cells - destroy API CMD cells of specific chain
  612. * @chain: the API CMD specific chain to destroy its cells
  613. * @num_cells: number of cells to destroy
  614. **/
  615. static void api_cmd_destroy_cells(struct hinic_api_cmd_chain *chain,
  616. int num_cells)
  617. {
  618. int cell_idx;
  619. for (cell_idx = 0; cell_idx < num_cells; cell_idx++)
  620. api_cmd_destroy_cell(chain, cell_idx);
  621. }
  622. /**
  623. * api_cmd_create_cells - create API CMD cells for specific chain
  624. * @chain: the API CMD specific chain
  625. *
  626. * Return 0 - Success, negative - Failure
  627. **/
  628. static int api_cmd_create_cells(struct hinic_api_cmd_chain *chain)
  629. {
  630. struct hinic_api_cmd_cell *node = NULL, *pre_node = NULL;
  631. struct hinic_hwif *hwif = chain->hwif;
  632. struct pci_dev *pdev = hwif->pdev;
  633. int err, cell_idx;
  634. for (cell_idx = 0; cell_idx < chain->num_cells; cell_idx++) {
  635. err = api_cmd_create_cell(chain, cell_idx, pre_node, &node);
  636. if (err) {
  637. dev_err(&pdev->dev, "Failed to create API CMD cell\n");
  638. goto err_create_cell;
  639. }
  640. pre_node = node;
  641. }
  642. /* set the Final node to point on the start */
  643. node->next_cell_paddr = cpu_to_be64(chain->head_cell_paddr);
  644. /* set the current node to be the head */
  645. chain->curr_node = chain->head_node;
  646. return 0;
  647. err_create_cell:
  648. api_cmd_destroy_cells(chain, cell_idx);
  649. return err;
  650. }
  651. /**
  652. * api_chain_init - initialize API CMD specific chain
  653. * @chain: the API CMD specific chain to initialize
  654. * @attr: attributes to set in the chain
  655. *
  656. * Return 0 - Success, negative - Failure
  657. **/
  658. static int api_chain_init(struct hinic_api_cmd_chain *chain,
  659. struct hinic_api_cmd_chain_attr *attr)
  660. {
  661. struct hinic_hwif *hwif = attr->hwif;
  662. struct pci_dev *pdev = hwif->pdev;
  663. size_t cell_ctxt_size;
  664. chain->hwif = hwif;
  665. chain->chain_type = attr->chain_type;
  666. chain->num_cells = attr->num_cells;
  667. chain->cell_size = attr->cell_size;
  668. chain->prod_idx = 0;
  669. chain->cons_idx = 0;
  670. sema_init(&chain->sem, 1);
  671. cell_ctxt_size = chain->num_cells * sizeof(*chain->cell_ctxt);
  672. chain->cell_ctxt = devm_kzalloc(&pdev->dev, cell_ctxt_size, GFP_KERNEL);
  673. if (!chain->cell_ctxt)
  674. return -ENOMEM;
  675. chain->wb_status = dma_zalloc_coherent(&pdev->dev,
  676. sizeof(*chain->wb_status),
  677. &chain->wb_status_paddr,
  678. GFP_KERNEL);
  679. if (!chain->wb_status) {
  680. dev_err(&pdev->dev, "Failed to allocate DMA wb status\n");
  681. return -ENOMEM;
  682. }
  683. return 0;
  684. }
  685. /**
  686. * api_chain_free - free API CMD specific chain
  687. * @chain: the API CMD specific chain to free
  688. **/
  689. static void api_chain_free(struct hinic_api_cmd_chain *chain)
  690. {
  691. struct hinic_hwif *hwif = chain->hwif;
  692. struct pci_dev *pdev = hwif->pdev;
  693. dma_free_coherent(&pdev->dev, sizeof(*chain->wb_status),
  694. chain->wb_status, chain->wb_status_paddr);
  695. }
  696. /**
  697. * api_cmd_create_chain - create API CMD specific chain
  698. * @attr: attributes to set the chain
  699. *
  700. * Return the created chain
  701. **/
  702. static struct hinic_api_cmd_chain *
  703. api_cmd_create_chain(struct hinic_api_cmd_chain_attr *attr)
  704. {
  705. struct hinic_hwif *hwif = attr->hwif;
  706. struct pci_dev *pdev = hwif->pdev;
  707. struct hinic_api_cmd_chain *chain;
  708. int err;
  709. if (attr->num_cells & (attr->num_cells - 1)) {
  710. dev_err(&pdev->dev, "Invalid number of cells, must be power of 2\n");
  711. return ERR_PTR(-EINVAL);
  712. }
  713. chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
  714. if (!chain)
  715. return ERR_PTR(-ENOMEM);
  716. err = api_chain_init(chain, attr);
  717. if (err) {
  718. dev_err(&pdev->dev, "Failed to initialize chain\n");
  719. return ERR_PTR(err);
  720. }
  721. err = api_cmd_create_cells(chain);
  722. if (err) {
  723. dev_err(&pdev->dev, "Failed to create cells for API CMD chain\n");
  724. goto err_create_cells;
  725. }
  726. err = api_cmd_chain_hw_init(chain);
  727. if (err) {
  728. dev_err(&pdev->dev, "Failed to initialize chain HW\n");
  729. goto err_chain_hw_init;
  730. }
  731. return chain;
  732. err_chain_hw_init:
  733. api_cmd_destroy_cells(chain, chain->num_cells);
  734. err_create_cells:
  735. api_chain_free(chain);
  736. return ERR_PTR(err);
  737. }
  738. /**
  739. * api_cmd_destroy_chain - destroy API CMD specific chain
  740. * @chain: the API CMD specific chain to destroy
  741. **/
  742. static void api_cmd_destroy_chain(struct hinic_api_cmd_chain *chain)
  743. {
  744. api_cmd_chain_hw_clean(chain);
  745. api_cmd_destroy_cells(chain, chain->num_cells);
  746. api_chain_free(chain);
  747. }
  748. /**
  749. * hinic_api_cmd_init - Initialize all the API CMD chains
  750. * @chain: the API CMD chains that are initialized
  751. * @hwif: the hardware interface of a pci function device
  752. *
  753. * Return 0 - Success, negative - Failure
  754. **/
  755. int hinic_api_cmd_init(struct hinic_api_cmd_chain **chain,
  756. struct hinic_hwif *hwif)
  757. {
  758. enum hinic_api_cmd_chain_type type, chain_type;
  759. struct hinic_api_cmd_chain_attr attr;
  760. struct pci_dev *pdev = hwif->pdev;
  761. size_t hw_cell_sz;
  762. int err;
  763. hw_cell_sz = sizeof(struct hinic_api_cmd_cell);
  764. attr.hwif = hwif;
  765. attr.num_cells = API_CHAIN_NUM_CELLS;
  766. attr.cell_size = API_CMD_CELL_SIZE(hw_cell_sz);
  767. chain_type = HINIC_API_CMD_WRITE_TO_MGMT_CPU;
  768. for ( ; chain_type < HINIC_API_CMD_MAX; chain_type++) {
  769. attr.chain_type = chain_type;
  770. if (chain_type != HINIC_API_CMD_WRITE_TO_MGMT_CPU)
  771. continue;
  772. chain[chain_type] = api_cmd_create_chain(&attr);
  773. if (IS_ERR(chain[chain_type])) {
  774. dev_err(&pdev->dev, "Failed to create chain %d\n",
  775. chain_type);
  776. err = PTR_ERR(chain[chain_type]);
  777. goto err_create_chain;
  778. }
  779. }
  780. return 0;
  781. err_create_chain:
  782. type = HINIC_API_CMD_WRITE_TO_MGMT_CPU;
  783. for ( ; type < chain_type; type++) {
  784. if (type != HINIC_API_CMD_WRITE_TO_MGMT_CPU)
  785. continue;
  786. api_cmd_destroy_chain(chain[type]);
  787. }
  788. return err;
  789. }
  790. /**
  791. * hinic_api_cmd_free - free the API CMD chains
  792. * @chain: the API CMD chains that are freed
  793. **/
  794. void hinic_api_cmd_free(struct hinic_api_cmd_chain **chain)
  795. {
  796. enum hinic_api_cmd_chain_type chain_type;
  797. chain_type = HINIC_API_CMD_WRITE_TO_MGMT_CPU;
  798. for ( ; chain_type < HINIC_API_CMD_MAX; chain_type++) {
  799. if (chain_type != HINIC_API_CMD_WRITE_TO_MGMT_CPU)
  800. continue;
  801. api_cmd_destroy_chain(chain[chain_type]);
  802. }
  803. }