You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmdif_comm.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. /*
  2. This software is available to you under a choice of one of two
  3. licenses. You may choose to be licensed under the terms of the GNU
  4. General Public License (GPL) Version 2, available at
  5. <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
  6. license, available in the LICENSE.TXT file accompanying this
  7. software. These details are also available at
  8. <http://openib.org/license.html>.
  9. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  10. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  11. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  12. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  13. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  14. ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  15. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  16. SOFTWARE.
  17. Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
  18. */
  19. #include "cmdif.h"
  20. #include "cmdif_comm.h"
  21. #include "cmdif_priv.h"
  22. static int cmdif_is_free(int *is_free)
  23. {
  24. int rc;
  25. __u32 result;
  26. rc = gw_read_cr(HCR_OFFSET_GO, &result);
  27. if (rc) {
  28. eprintf("");
  29. return rc;
  30. }
  31. *is_free = (result & 0x800000) == 0;
  32. return 0;
  33. }
  34. static void edit_hcr(command_fields_t * cmd_prms, __u32 * buf)
  35. {
  36. unsigned int i;
  37. switch (cmd_prms->in_trans) {
  38. case TRANS_NA:
  39. /* note! since these are zeroes I do not bother to deal with endianess */
  40. buf[0] = 0;
  41. buf[1] = 0;
  42. break;
  43. case TRANS_IMMEDIATE:
  44. buf[0] = cmd_prms->in_param[0];
  45. buf[1] = cmd_prms->in_param[1];
  46. break;
  47. case TRANS_MAILBOX:
  48. buf[0] = 0;
  49. buf[1] = virt_to_bus(cmd_prms->in_param);
  50. for (i = 0; i < cmd_prms->in_param_size; i += 4)
  51. cmd_prms->in_param[i >> 2] =
  52. cpu_to_be32(cmd_prms->in_param[i >> 2]);
  53. break;
  54. }
  55. buf[2] = cmd_prms->input_modifier;
  56. switch (cmd_prms->out_trans) {
  57. case TRANS_NA:
  58. /* note! since these are zeroes I do not bother to deal with endianess */
  59. buf[3] = 0;
  60. buf[4] = 0;
  61. break;
  62. case TRANS_IMMEDIATE:
  63. break;
  64. case TRANS_MAILBOX:
  65. buf[3] = 0;
  66. buf[4] = virt_to_bus(cmd_prms->out_param);
  67. break;
  68. }
  69. buf[5] = 0; /* token is always 0 */
  70. buf[6] = cmd_prms->opcode | /* opcode */
  71. 0x800000 | /* go bit */
  72. ((cmd_prms->opcode_modifier & 0xf) << 12); /* opcode modifier
  73. */ }
  74. static int wait_cmdif_free(void)
  75. {
  76. int ret, is_free;
  77. unsigned int i, relax_time = 1, max_time = 5000;
  78. /* wait until go bit is free */
  79. for (i = 0; i < max_time; i += relax_time) {
  80. ret = cmdif_is_free(&is_free);
  81. if (ret)
  82. return ret;
  83. if (is_free)
  84. break;
  85. mdelay(relax_time);
  86. }
  87. if (i >= max_time)
  88. return -1;
  89. return 0;
  90. }
  91. static XHH_cmd_status_t cmd_invoke(command_fields_t * cmd_prms)
  92. {
  93. int ret, is_free, i;
  94. __u32 hcr[7], data;
  95. __u8 status;
  96. /* check if go bit is free */
  97. ret = cmdif_is_free(&is_free);
  98. if (ret) {
  99. eprintf("");
  100. return -1;
  101. }
  102. __asm__ __volatile__("":::"memory");
  103. /* it must be free */
  104. if (!is_free) {
  105. eprintf("");
  106. return -1;
  107. }
  108. __asm__ __volatile__("":::"memory");
  109. edit_hcr(cmd_prms, hcr);
  110. __asm__ __volatile__("":::"memory");
  111. for (i = 0; i < 7; ++i) {
  112. ret = gw_write_cr(HCR_BASE + i * 4, hcr[i]);
  113. if (ret) {
  114. eprintf("");
  115. return -1;
  116. }
  117. }
  118. __asm__ __volatile__("":::"memory");
  119. /* wait for completion */
  120. ret = wait_cmdif_free();
  121. if (ret) {
  122. eprintf("");
  123. return -1;
  124. }
  125. __asm__ __volatile__("":::"memory");
  126. ret = gw_read_cr(HCR_OFFSET_STATUS, &data);
  127. if (ret) {
  128. eprintf("");
  129. return -1;
  130. }
  131. status = data >> 24;
  132. if (status) {
  133. tprintf("status=0x%x", status);
  134. return status;
  135. }
  136. if (cmd_prms->out_trans == TRANS_MAILBOX)
  137. be_to_cpu_buf(cmd_prms->out_param, cmd_prms->out_param_size);
  138. else if (cmd_prms->out_trans == TRANS_IMMEDIATE) {
  139. if (gw_read_cr(HCR_OFFSET_OUTPRM_H, &cmd_prms->out_param[0]))
  140. return -1;
  141. if (gw_read_cr(HCR_OFFSET_OUTPRM_L, &cmd_prms->out_param[1]))
  142. return -1;
  143. }
  144. return 0;
  145. }
  146. /*************************************************
  147. commands
  148. *************************************************/
  149. /*
  150. * cmd_close_hca
  151. */
  152. static int cmd_close_hca(int panic)
  153. {
  154. int rc;
  155. command_fields_t cmd_desc;
  156. memset(&cmd_desc, 0, sizeof cmd_desc);
  157. cmd_desc.opcode = XDEV_CMD_CLOSE_HCA;
  158. cmd_desc.opcode_modifier= panic;
  159. rc = cmd_invoke(&cmd_desc);
  160. return rc;
  161. }
  162. /*
  163. * cmd_init_hca
  164. */
  165. static int cmd_init_hca(__u32 * inprm, __u32 in_prm_size)
  166. {
  167. int rc;
  168. command_fields_t cmd_desc;
  169. memset(&cmd_desc, 0, sizeof cmd_desc);
  170. cmd_desc.in_trans = TRANS_MAILBOX;
  171. cmd_desc.opcode = XDEV_CMD_INIT_HCA;
  172. cmd_desc.in_param = inprm;
  173. cmd_desc.in_param_size = in_prm_size;
  174. rc = cmd_invoke(&cmd_desc);
  175. return rc;
  176. }
  177. /*
  178. * cmd_sw2hw_eq
  179. */
  180. static int cmd_sw2hw_eq(__u32 inprm_sz)
  181. {
  182. int rc;
  183. command_fields_t cmd_desc;
  184. void *inprm;
  185. memset(&cmd_desc, 0, sizeof cmd_desc);
  186. inprm = get_inprm_buf();
  187. cmd_desc.in_trans = TRANS_MAILBOX;
  188. cmd_desc.opcode = XDEV_CMD_SW2HW_EQ;
  189. cmd_desc.in_param = inprm;
  190. cmd_desc.in_param_size = inprm_sz;
  191. rc = cmd_invoke(&cmd_desc);
  192. return rc;
  193. }
  194. /*
  195. * cmd_hw2sw_eq
  196. */
  197. static int cmd_hw2sw_eq(__u8 eqn)
  198. {
  199. int rc;
  200. command_fields_t cmd_desc;
  201. void *outprm;
  202. memset(&cmd_desc, 0, sizeof cmd_desc);
  203. outprm = get_outprm_buf();
  204. cmd_desc.opcode = XDEV_CMD_HW2SW_EQ;
  205. cmd_desc.input_modifier = eqn;
  206. cmd_desc.out_trans = TRANS_MAILBOX;
  207. cmd_desc.out_param = outprm;
  208. cmd_desc.out_param_size = 0x40;
  209. rc = cmd_invoke(&cmd_desc);
  210. return rc;
  211. }
  212. /*
  213. * cmd_map_eq
  214. */
  215. static int cmd_map_eq(__u8 eqn, __u32 mask, int map)
  216. {
  217. int rc;
  218. command_fields_t cmd_desc;
  219. __u32 *inprm;
  220. memset(&cmd_desc, 0, sizeof cmd_desc);
  221. inprm = get_inprm_buf();
  222. inprm[1] = mask;
  223. inprm[0] = 0;
  224. cmd_desc.opcode = XDEV_CMD_MAP_EQ;
  225. cmd_desc.in_trans = TRANS_IMMEDIATE;
  226. cmd_desc.in_param = inprm;
  227. cmd_desc.input_modifier = ((map ? 0 : 1) << 31) | eqn;
  228. rc = cmd_invoke(&cmd_desc);
  229. return rc;
  230. }
  231. /*
  232. * cmd_sw2hw_mpt
  233. */
  234. static int cmd_sw2hw_mpt(__u32 * lkey, __u32 in_key, __u32 * inprm,
  235. __u32 inprm_sz)
  236. {
  237. int rc;
  238. command_fields_t cmd_desc;
  239. memset(&cmd_desc, 0, sizeof cmd_desc);
  240. cmd_desc.in_trans = TRANS_MAILBOX;
  241. cmd_desc.opcode = XDEV_CMD_SW2HW_MPT;
  242. cmd_desc.input_modifier = in_key & MKEY_IDX_MASK; /* only one MR for the whole driver */
  243. cmd_desc.in_param = inprm;
  244. cmd_desc.in_param_size = inprm_sz;
  245. rc = cmd_invoke(&cmd_desc);
  246. if (!rc)
  247. *lkey = in_key;
  248. return rc;
  249. }
  250. /*
  251. * cmd_hw2sw_mpt
  252. */
  253. static int cmd_hw2sw_mpt(__u32 key)
  254. {
  255. int rc;
  256. command_fields_t cmd_desc;
  257. memset(&cmd_desc, 0, sizeof cmd_desc);
  258. cmd_desc.opcode = XDEV_CMD_HW2SW_MPT;
  259. cmd_desc.input_modifier = key & MKEY_IDX_MASK;
  260. cmd_desc.opcode_modifier = 1;
  261. rc = cmd_invoke(&cmd_desc);
  262. return rc;
  263. }
  264. /*
  265. * cmd_init_ib
  266. */
  267. static int cmd_init_ib(__u32 port, __u32 * inprm, __u32 inprm_sz)
  268. {
  269. int rc;
  270. command_fields_t cmd_desc;
  271. memset(&cmd_desc, 0, sizeof cmd_desc);
  272. cmd_desc.opcode = XDEV_CMD_INIT_IB;
  273. cmd_desc.input_modifier = port;
  274. cmd_desc.in_trans = TRANS_MAILBOX;
  275. cmd_desc.in_param = inprm;
  276. cmd_desc.in_param_size = inprm_sz;
  277. rc = cmd_invoke(&cmd_desc);
  278. return rc;
  279. }
  280. /*
  281. * cmd_close_ib
  282. */
  283. static int cmd_close_ib(__u32 port)
  284. {
  285. int rc;
  286. command_fields_t cmd_desc;
  287. memset(&cmd_desc, 0, sizeof cmd_desc);
  288. cmd_desc.opcode = XDEV_CMD_CLOSE_IB;
  289. cmd_desc.input_modifier = port;
  290. rc = cmd_invoke(&cmd_desc);
  291. return rc;
  292. }
  293. /*
  294. * cmd_sw2hw_cq
  295. */
  296. static int cmd_sw2hw_cq(__u32 cqn, __u32 * inprm, __u32 inprm_sz)
  297. {
  298. int rc;
  299. command_fields_t cmd_desc;
  300. memset(&cmd_desc, 0, sizeof cmd_desc);
  301. cmd_desc.opcode = XDEV_CMD_SW2HW_CQ;
  302. cmd_desc.in_trans = TRANS_MAILBOX;
  303. cmd_desc.in_param = inprm;
  304. cmd_desc.in_param_size = inprm_sz;
  305. cmd_desc.input_modifier = cqn;
  306. rc = cmd_invoke(&cmd_desc);
  307. return rc;
  308. }
  309. /*
  310. * cmd_hw2sw_cq
  311. */
  312. static int cmd_hw2sw_cq(__u32 cqn)
  313. {
  314. int rc;
  315. command_fields_t cmd_desc;
  316. memset(&cmd_desc, 0, sizeof cmd_desc);
  317. cmd_desc.opcode = XDEV_CMD_HW2SW_CQ;
  318. cmd_desc.input_modifier = cqn;
  319. cmd_desc.out_trans = TRANS_MAILBOX;
  320. cmd_desc.out_param = get_outprm_buf();
  321. rc = cmd_invoke(&cmd_desc);
  322. return rc;
  323. }
  324. /*
  325. * cmd_rst2init_qpee
  326. */
  327. static int cmd_rst2init_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
  328. {
  329. int rc;
  330. command_fields_t cmd_desc;
  331. memset(&cmd_desc, 0, sizeof cmd_desc);
  332. cmd_desc.opcode = XDEV_CMD_RST2INIT_QPEE;
  333. cmd_desc.in_trans = TRANS_MAILBOX;
  334. cmd_desc.in_param = inprm;
  335. cmd_desc.in_param_size = inprm_sz;
  336. cmd_desc.input_modifier = qpn;
  337. rc = cmd_invoke(&cmd_desc);
  338. return rc;
  339. }
  340. /*
  341. * cmd_init2rtr_qpee
  342. */
  343. static int cmd_init2rtr_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
  344. {
  345. int rc;
  346. command_fields_t cmd_desc;
  347. memset(&cmd_desc, 0, sizeof cmd_desc);
  348. cmd_desc.opcode = XDEV_CMD_INIT2RTR_QPEE;
  349. cmd_desc.in_trans = TRANS_MAILBOX;
  350. cmd_desc.in_param = inprm;
  351. cmd_desc.in_param_size = inprm_sz;
  352. cmd_desc.input_modifier = qpn;;
  353. rc = cmd_invoke(&cmd_desc);
  354. return rc;
  355. }
  356. /*
  357. * cmd_rtr2rts_qpee
  358. */
  359. static int cmd_rtr2rts_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
  360. {
  361. int rc;
  362. command_fields_t cmd_desc;
  363. memset(&cmd_desc, 0, sizeof cmd_desc);
  364. cmd_desc.opcode = XDEV_CMD_RTR2RTS_QPEE;
  365. cmd_desc.in_trans = TRANS_MAILBOX;
  366. cmd_desc.in_param = inprm;
  367. cmd_desc.in_param_size = inprm_sz;
  368. cmd_desc.input_modifier = qpn;
  369. rc = cmd_invoke(&cmd_desc);
  370. return rc;
  371. }
  372. /*
  373. * cmd_2rst_qpee
  374. */
  375. static int cmd_2rst_qpee(__u32 qpn)
  376. {
  377. int rc;
  378. command_fields_t cmd_desc;
  379. memset(&cmd_desc, 0, sizeof cmd_desc);
  380. cmd_desc.opcode = XDEV_CMD_ERR2RST_QPEE;
  381. cmd_desc.opcode_modifier = 0;
  382. cmd_desc.input_modifier = qpn;
  383. cmd_desc.out_trans = TRANS_MAILBOX;
  384. cmd_desc.out_param = get_outprm_buf();
  385. rc = cmd_invoke(&cmd_desc);
  386. return rc;
  387. }
  388. /*
  389. * cmd_2err_qpee
  390. */
  391. static int cmd_2err_qpee(__u32 qpn)
  392. {
  393. int rc;
  394. command_fields_t cmd_desc;
  395. memset(&cmd_desc, 0, sizeof cmd_desc);
  396. cmd_desc.opcode = XDEV_CMD_2ERR_QPEE;
  397. cmd_desc.input_modifier = qpn;
  398. rc = cmd_invoke(&cmd_desc);
  399. return rc;
  400. }
  401. /*
  402. * cmd_post_doorbell
  403. */
  404. static int cmd_post_doorbell(void *inprm, __u32 offset)
  405. {
  406. int rc;
  407. command_fields_t cmd_desc;
  408. memset(&cmd_desc, 0, sizeof cmd_desc);
  409. cmd_desc.opcode = XDEV_CMD_POST_DOORBELL;
  410. cmd_desc.in_trans = TRANS_IMMEDIATE;
  411. cmd_desc.in_param = inprm;
  412. cmd_desc.input_modifier = offset;
  413. if (0) {
  414. rc = cmd_invoke(&cmd_desc);
  415. } else {
  416. dev_post_dbell(inprm, offset);
  417. rc = 0;
  418. }
  419. return rc;
  420. }
  421. static int cmd_mad_ifc(void *inprm, struct ib_mad_st *mad, __u8 port)
  422. {
  423. int rc;
  424. command_fields_t cmd_desc;
  425. memset(&cmd_desc, 0, sizeof cmd_desc);
  426. cmd_desc.opcode = XDEV_CMD_MAD_IFC;
  427. cmd_desc.opcode_modifier = 1; /* no mkey/bkey validation */
  428. cmd_desc.input_modifier = port;
  429. cmd_desc.in_trans = TRANS_MAILBOX;
  430. cmd_desc.in_param_size = 256;
  431. cmd_desc.in_param = (__u32 *) inprm;
  432. cmd_desc.out_trans = TRANS_MAILBOX;
  433. cmd_desc.out_param = (__u32 *) mad;
  434. cmd_desc.out_param_size = 256;
  435. rc = cmd_invoke(&cmd_desc);
  436. return rc;
  437. }
  438. static int cmd_mgid_hash(__u8 * gid, __u16 * mgid_hash_p)
  439. {
  440. int rc;
  441. command_fields_t cmd_desc;
  442. __u16 result[2];
  443. memset(&cmd_desc, 0, sizeof cmd_desc);
  444. cmd_desc.opcode = XDEV_CMD_MGID_HASH;
  445. cmd_desc.in_trans = TRANS_MAILBOX;
  446. cmd_desc.in_param = (__u32 *) gid;
  447. cmd_desc.in_param_size = 16;
  448. cmd_desc.out_trans = TRANS_IMMEDIATE;
  449. rc = cmd_invoke(&cmd_desc);
  450. if (!rc) {
  451. rc = gw_read_cr(HCR_BASE + 16, (__u32 *) result);
  452. if (!rc) {
  453. *mgid_hash_p = result[0];
  454. }
  455. }
  456. return rc;
  457. }