Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmdif_comm.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  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. DBG ( "Executing command:\n" );
  97. /* check if go bit is free */
  98. ret = cmdif_is_free(&is_free);
  99. if (ret) {
  100. eprintf("");
  101. return -1;
  102. }
  103. __asm__ __volatile__("":::"memory");
  104. /* it must be free */
  105. if (!is_free) {
  106. eprintf("");
  107. return -1;
  108. }
  109. __asm__ __volatile__("":::"memory");
  110. edit_hcr(cmd_prms, hcr);
  111. __asm__ __volatile__("":::"memory");
  112. DBG_HD ( &hcr[0], sizeof ( hcr ) );
  113. if ( cmd_prms->in_trans == TRANS_MAILBOX ) {
  114. size_t size = ( 4 * cmd_prms->in_param_size );
  115. if ( size > 256 )
  116. size = 256;
  117. #if ! CREATE_OWN
  118. DBG ( "Input mailbox:\n" );
  119. DBG_HD ( &cmd_prms->in_param[0], size );
  120. #endif
  121. }
  122. for (i = 0; i < 7; ++i) {
  123. ret = gw_write_cr(HCR_BASE + i * 4, hcr[i]);
  124. if (ret) {
  125. eprintf("");
  126. return -1;
  127. }
  128. }
  129. __asm__ __volatile__("":::"memory");
  130. /* wait for completion */
  131. ret = wait_cmdif_free();
  132. if (ret) {
  133. eprintf("");
  134. return -1;
  135. }
  136. __asm__ __volatile__("":::"memory");
  137. ret = gw_read_cr(HCR_OFFSET_STATUS, &data);
  138. if (ret) {
  139. eprintf("");
  140. return -1;
  141. }
  142. status = data >> 24;
  143. if (status) {
  144. tprintf("status=0x%x", status);
  145. return status;
  146. }
  147. if (cmd_prms->out_trans == TRANS_MAILBOX)
  148. be_to_cpu_buf(cmd_prms->out_param, cmd_prms->out_param_size);
  149. else if (cmd_prms->out_trans == TRANS_IMMEDIATE) {
  150. if (gw_read_cr(HCR_OFFSET_OUTPRM_H, &cmd_prms->out_param[0]))
  151. return -1;
  152. if (gw_read_cr(HCR_OFFSET_OUTPRM_L, &cmd_prms->out_param[1]))
  153. return -1;
  154. }
  155. if ( cmd_prms->out_trans == TRANS_MAILBOX ) {
  156. size_t size = ( 4 * cmd_prms->out_param_size );
  157. if ( size > 256 )
  158. size = 256;
  159. #if ! CREATE_OWN
  160. DBG ( "Output mailbox:\n" );
  161. DBG_HD ( &cmd_prms->out_param[0], size );
  162. #endif
  163. }
  164. DBG ( "Command executed successfully\n" );
  165. return 0;
  166. }
  167. /*************************************************
  168. commands
  169. *************************************************/
  170. /*
  171. * cmd_close_hca
  172. */
  173. static int cmd_close_hca(int panic)
  174. {
  175. int rc;
  176. command_fields_t cmd_desc;
  177. memset(&cmd_desc, 0, sizeof cmd_desc);
  178. cmd_desc.opcode = XDEV_CMD_CLOSE_HCA;
  179. cmd_desc.opcode_modifier= panic;
  180. rc = cmd_invoke(&cmd_desc);
  181. return rc;
  182. }
  183. /*
  184. * cmd_init_hca
  185. */
  186. static int cmd_init_hca(__u32 * inprm, __u32 in_prm_size)
  187. {
  188. int rc;
  189. command_fields_t cmd_desc;
  190. memset(&cmd_desc, 0, sizeof cmd_desc);
  191. cmd_desc.in_trans = TRANS_MAILBOX;
  192. cmd_desc.opcode = XDEV_CMD_INIT_HCA;
  193. cmd_desc.in_param = inprm;
  194. cmd_desc.in_param_size = in_prm_size;
  195. rc = cmd_invoke(&cmd_desc);
  196. return rc;
  197. }
  198. /*
  199. * cmd_sw2hw_eq
  200. */
  201. static int cmd_sw2hw_eq(__u32 inprm_sz)
  202. {
  203. int rc;
  204. command_fields_t cmd_desc;
  205. void *inprm;
  206. memset(&cmd_desc, 0, sizeof cmd_desc);
  207. inprm = get_inprm_buf();
  208. cmd_desc.in_trans = TRANS_MAILBOX;
  209. cmd_desc.opcode = XDEV_CMD_SW2HW_EQ;
  210. cmd_desc.in_param = inprm;
  211. cmd_desc.in_param_size = inprm_sz;
  212. rc = cmd_invoke(&cmd_desc);
  213. return rc;
  214. }
  215. /*
  216. * cmd_hw2sw_eq
  217. */
  218. static int cmd_hw2sw_eq(__u8 eqn)
  219. {
  220. int rc;
  221. command_fields_t cmd_desc;
  222. void *outprm;
  223. memset(&cmd_desc, 0, sizeof cmd_desc);
  224. outprm = get_outprm_buf();
  225. cmd_desc.opcode = XDEV_CMD_HW2SW_EQ;
  226. cmd_desc.input_modifier = eqn;
  227. cmd_desc.out_trans = TRANS_MAILBOX;
  228. cmd_desc.out_param = outprm;
  229. cmd_desc.out_param_size = 0x40;
  230. rc = cmd_invoke(&cmd_desc);
  231. return rc;
  232. }
  233. /*
  234. * cmd_map_eq
  235. */
  236. static int cmd_map_eq(__u8 eqn, __u32 mask, int map)
  237. {
  238. int rc;
  239. command_fields_t cmd_desc;
  240. __u32 *inprm;
  241. memset(&cmd_desc, 0, sizeof cmd_desc);
  242. inprm = get_inprm_buf();
  243. inprm[1] = mask;
  244. inprm[0] = 0;
  245. cmd_desc.opcode = XDEV_CMD_MAP_EQ;
  246. cmd_desc.in_trans = TRANS_IMMEDIATE;
  247. cmd_desc.in_param = inprm;
  248. cmd_desc.input_modifier = ((map ? 0 : 1) << 31) | eqn;
  249. rc = cmd_invoke(&cmd_desc);
  250. return rc;
  251. }
  252. /*
  253. * cmd_sw2hw_mpt
  254. */
  255. static int cmd_sw2hw_mpt(__u32 * lkey, __u32 in_key, __u32 * inprm,
  256. __u32 inprm_sz)
  257. {
  258. int rc;
  259. command_fields_t cmd_desc;
  260. memset(&cmd_desc, 0, sizeof cmd_desc);
  261. cmd_desc.in_trans = TRANS_MAILBOX;
  262. cmd_desc.opcode = XDEV_CMD_SW2HW_MPT;
  263. cmd_desc.input_modifier = in_key & MKEY_IDX_MASK; /* only one MR for the whole driver */
  264. cmd_desc.in_param = inprm;
  265. cmd_desc.in_param_size = inprm_sz;
  266. rc = cmd_invoke(&cmd_desc);
  267. if (!rc)
  268. *lkey = in_key;
  269. return rc;
  270. }
  271. /*
  272. * cmd_hw2sw_mpt
  273. */
  274. static int cmd_hw2sw_mpt(__u32 key)
  275. {
  276. int rc;
  277. command_fields_t cmd_desc;
  278. memset(&cmd_desc, 0, sizeof cmd_desc);
  279. cmd_desc.opcode = XDEV_CMD_HW2SW_MPT;
  280. cmd_desc.input_modifier = key & MKEY_IDX_MASK;
  281. cmd_desc.opcode_modifier = 1;
  282. rc = cmd_invoke(&cmd_desc);
  283. return rc;
  284. }
  285. /*
  286. * cmd_init_ib
  287. */
  288. static int cmd_init_ib(__u32 port, __u32 * inprm, __u32 inprm_sz)
  289. {
  290. int rc;
  291. command_fields_t cmd_desc;
  292. memset(&cmd_desc, 0, sizeof cmd_desc);
  293. cmd_desc.opcode = XDEV_CMD_INIT_IB;
  294. cmd_desc.input_modifier = port;
  295. cmd_desc.in_trans = TRANS_MAILBOX;
  296. cmd_desc.in_param = inprm;
  297. cmd_desc.in_param_size = inprm_sz;
  298. rc = cmd_invoke(&cmd_desc);
  299. return rc;
  300. }
  301. /*
  302. * cmd_close_ib
  303. */
  304. static int cmd_close_ib(__u32 port)
  305. {
  306. int rc;
  307. command_fields_t cmd_desc;
  308. memset(&cmd_desc, 0, sizeof cmd_desc);
  309. cmd_desc.opcode = XDEV_CMD_CLOSE_IB;
  310. cmd_desc.input_modifier = port;
  311. rc = cmd_invoke(&cmd_desc);
  312. return rc;
  313. }
  314. /*
  315. * cmd_sw2hw_cq
  316. */
  317. static int cmd_sw2hw_cq(__u32 cqn, __u32 * inprm, __u32 inprm_sz)
  318. {
  319. int rc;
  320. command_fields_t cmd_desc;
  321. memset(&cmd_desc, 0, sizeof cmd_desc);
  322. cmd_desc.opcode = XDEV_CMD_SW2HW_CQ;
  323. cmd_desc.in_trans = TRANS_MAILBOX;
  324. cmd_desc.in_param = inprm;
  325. cmd_desc.in_param_size = inprm_sz;
  326. cmd_desc.input_modifier = cqn;
  327. rc = cmd_invoke(&cmd_desc);
  328. return rc;
  329. }
  330. /*
  331. * cmd_hw2sw_cq
  332. */
  333. static int cmd_hw2sw_cq(__u32 cqn)
  334. {
  335. int rc;
  336. command_fields_t cmd_desc;
  337. memset(&cmd_desc, 0, sizeof cmd_desc);
  338. cmd_desc.opcode = XDEV_CMD_HW2SW_CQ;
  339. cmd_desc.input_modifier = cqn;
  340. cmd_desc.out_trans = TRANS_MAILBOX;
  341. cmd_desc.out_param = get_outprm_buf();
  342. rc = cmd_invoke(&cmd_desc);
  343. return rc;
  344. }
  345. /*
  346. * cmd_rst2init_qpee
  347. */
  348. static int cmd_rst2init_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
  349. {
  350. int rc;
  351. command_fields_t cmd_desc;
  352. memset(&cmd_desc, 0, sizeof cmd_desc);
  353. cmd_desc.opcode = XDEV_CMD_RST2INIT_QPEE;
  354. cmd_desc.in_trans = TRANS_MAILBOX;
  355. cmd_desc.in_param = inprm;
  356. cmd_desc.in_param_size = inprm_sz;
  357. cmd_desc.input_modifier = qpn;
  358. rc = cmd_invoke(&cmd_desc);
  359. return rc;
  360. }
  361. /*
  362. * cmd_init2rtr_qpee
  363. */
  364. static int cmd_init2rtr_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
  365. {
  366. int rc;
  367. command_fields_t cmd_desc;
  368. memset(&cmd_desc, 0, sizeof cmd_desc);
  369. cmd_desc.opcode = XDEV_CMD_INIT2RTR_QPEE;
  370. cmd_desc.in_trans = TRANS_MAILBOX;
  371. cmd_desc.in_param = inprm;
  372. cmd_desc.in_param_size = inprm_sz;
  373. cmd_desc.input_modifier = qpn;;
  374. rc = cmd_invoke(&cmd_desc);
  375. return rc;
  376. }
  377. /*
  378. * cmd_rtr2rts_qpee
  379. */
  380. static int cmd_rtr2rts_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
  381. {
  382. int rc;
  383. command_fields_t cmd_desc;
  384. memset(&cmd_desc, 0, sizeof cmd_desc);
  385. cmd_desc.opcode = XDEV_CMD_RTR2RTS_QPEE;
  386. cmd_desc.in_trans = TRANS_MAILBOX;
  387. cmd_desc.in_param = inprm;
  388. cmd_desc.in_param_size = inprm_sz;
  389. cmd_desc.input_modifier = qpn;
  390. rc = cmd_invoke(&cmd_desc);
  391. return rc;
  392. }
  393. /*
  394. * cmd_2rst_qpee
  395. */
  396. static int cmd_2rst_qpee(__u32 qpn)
  397. {
  398. int rc;
  399. command_fields_t cmd_desc;
  400. memset(&cmd_desc, 0, sizeof cmd_desc);
  401. cmd_desc.opcode = XDEV_CMD_ERR2RST_QPEE;
  402. cmd_desc.opcode_modifier = 0;
  403. cmd_desc.input_modifier = qpn;
  404. cmd_desc.out_trans = TRANS_MAILBOX;
  405. cmd_desc.out_param = get_outprm_buf();
  406. rc = cmd_invoke(&cmd_desc);
  407. return rc;
  408. }
  409. /*
  410. * cmd_2err_qpee
  411. */
  412. static int cmd_2err_qpee(__u32 qpn)
  413. {
  414. int rc;
  415. command_fields_t cmd_desc;
  416. memset(&cmd_desc, 0, sizeof cmd_desc);
  417. cmd_desc.opcode = XDEV_CMD_2ERR_QPEE;
  418. cmd_desc.input_modifier = qpn;
  419. rc = cmd_invoke(&cmd_desc);
  420. return rc;
  421. }
  422. /*
  423. * cmd_post_doorbell
  424. */
  425. static int cmd_post_doorbell(void *inprm, __u32 offset)
  426. {
  427. int rc;
  428. command_fields_t cmd_desc;
  429. memset(&cmd_desc, 0, sizeof cmd_desc);
  430. cmd_desc.opcode = XDEV_CMD_POST_DOORBELL;
  431. cmd_desc.in_trans = TRANS_IMMEDIATE;
  432. cmd_desc.in_param = inprm;
  433. cmd_desc.input_modifier = offset;
  434. if (0) {
  435. rc = cmd_invoke(&cmd_desc);
  436. } else {
  437. dev_post_dbell(inprm, offset);
  438. rc = 0;
  439. }
  440. return rc;
  441. }
  442. static int cmd_mad_ifc(void *inprm, struct ib_mad_st *mad, __u8 port)
  443. {
  444. int rc;
  445. command_fields_t cmd_desc;
  446. memset(&cmd_desc, 0, sizeof cmd_desc);
  447. cmd_desc.opcode = XDEV_CMD_MAD_IFC;
  448. cmd_desc.opcode_modifier = 1; /* no mkey/bkey validation */
  449. cmd_desc.input_modifier = port;
  450. cmd_desc.in_trans = TRANS_MAILBOX;
  451. cmd_desc.in_param_size = 256;
  452. cmd_desc.in_param = (__u32 *) inprm;
  453. cmd_desc.out_trans = TRANS_MAILBOX;
  454. cmd_desc.out_param = (__u32 *) mad;
  455. cmd_desc.out_param_size = 256;
  456. rc = cmd_invoke(&cmd_desc);
  457. return rc;
  458. }
  459. static int cmd_mgid_hash(__u8 * gid, __u16 * mgid_hash_p)
  460. {
  461. int rc;
  462. command_fields_t cmd_desc;
  463. union {
  464. __u32 u32;
  465. __u16 u16[2];
  466. } result;
  467. memset(&cmd_desc, 0, sizeof cmd_desc);
  468. cmd_desc.opcode = XDEV_CMD_MGID_HASH;
  469. cmd_desc.in_trans = TRANS_MAILBOX;
  470. cmd_desc.in_param = (__u32 *) gid;
  471. cmd_desc.in_param_size = 16;
  472. cmd_desc.out_trans = TRANS_IMMEDIATE;
  473. rc = cmd_invoke(&cmd_desc);
  474. if (!rc) {
  475. rc = gw_read_cr(HCR_BASE + 16, &result.u32);
  476. if (!rc) {
  477. *mgid_hash_p = result.u16[0];
  478. }
  479. }
  480. return rc;
  481. }