cptvf_mbox.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright (C) 2016 Cavium, Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of version 2 of the GNU General Public License
  6. * as published by the Free Software Foundation.
  7. */
  8. #include "cptvf.h"
  9. static void cptvf_send_msg_to_pf(struct cpt_vf *cptvf, struct cpt_mbox *mbx)
  10. {
  11. /* Writing mbox(1) causes interrupt */
  12. cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0),
  13. mbx->msg);
  14. cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1),
  15. mbx->data);
  16. }
  17. /* ACKs PF's mailbox message
  18. */
  19. void cptvf_mbox_send_ack(struct cpt_vf *cptvf, struct cpt_mbox *mbx)
  20. {
  21. mbx->msg = CPT_MBOX_MSG_TYPE_ACK;
  22. cptvf_send_msg_to_pf(cptvf, mbx);
  23. }
  24. /* NACKs PF's mailbox message that VF is not able to
  25. * complete the action
  26. */
  27. void cptvf_mbox_send_nack(struct cpt_vf *cptvf, struct cpt_mbox *mbx)
  28. {
  29. mbx->msg = CPT_MBOX_MSG_TYPE_NACK;
  30. cptvf_send_msg_to_pf(cptvf, mbx);
  31. }
  32. /* Interrupt handler to handle mailbox messages from VFs */
  33. void cptvf_handle_mbox_intr(struct cpt_vf *cptvf)
  34. {
  35. struct cpt_mbox mbx = {};
  36. /*
  37. * MBOX[0] contains msg
  38. * MBOX[1] contains data
  39. */
  40. mbx.msg = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0));
  41. mbx.data = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1));
  42. dev_dbg(&cptvf->pdev->dev, "%s: Mailbox msg 0x%llx from PF\n",
  43. __func__, mbx.msg);
  44. switch (mbx.msg) {
  45. case CPT_MSG_READY:
  46. {
  47. cptvf->pf_acked = true;
  48. cptvf->vfid = mbx.data;
  49. dev_dbg(&cptvf->pdev->dev, "Received VFID %d\n", cptvf->vfid);
  50. break;
  51. }
  52. case CPT_MSG_QBIND_GRP:
  53. cptvf->pf_acked = true;
  54. cptvf->vftype = mbx.data;
  55. dev_dbg(&cptvf->pdev->dev, "VF %d type %s group %d\n",
  56. cptvf->vfid, ((mbx.data == SE_TYPES) ? "SE" : "AE"),
  57. cptvf->vfgrp);
  58. break;
  59. case CPT_MBOX_MSG_TYPE_ACK:
  60. cptvf->pf_acked = true;
  61. break;
  62. case CPT_MBOX_MSG_TYPE_NACK:
  63. cptvf->pf_nacked = true;
  64. break;
  65. default:
  66. dev_err(&cptvf->pdev->dev, "Invalid msg from PF, msg 0x%llx\n",
  67. mbx.msg);
  68. break;
  69. }
  70. }
  71. static int cptvf_send_msg_to_pf_timeout(struct cpt_vf *cptvf,
  72. struct cpt_mbox *mbx)
  73. {
  74. int timeout = CPT_MBOX_MSG_TIMEOUT;
  75. int sleep = 10;
  76. cptvf->pf_acked = false;
  77. cptvf->pf_nacked = false;
  78. cptvf_send_msg_to_pf(cptvf, mbx);
  79. /* Wait for previous message to be acked, timeout 2sec */
  80. while (!cptvf->pf_acked) {
  81. if (cptvf->pf_nacked)
  82. return -EINVAL;
  83. msleep(sleep);
  84. if (cptvf->pf_acked)
  85. break;
  86. timeout -= sleep;
  87. if (!timeout) {
  88. dev_err(&cptvf->pdev->dev, "PF didn't ack to mbox msg %llx from VF%u\n",
  89. (mbx->msg & 0xFF), cptvf->vfid);
  90. return -EBUSY;
  91. }
  92. }
  93. return 0;
  94. }
  95. /*
  96. * Checks if VF is able to comminicate with PF
  97. * and also gets the CPT number this VF is associated to.
  98. */
  99. int cptvf_check_pf_ready(struct cpt_vf *cptvf)
  100. {
  101. struct pci_dev *pdev = cptvf->pdev;
  102. struct cpt_mbox mbx = {};
  103. mbx.msg = CPT_MSG_READY;
  104. if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
  105. dev_err(&pdev->dev, "PF didn't respond to READY msg\n");
  106. return -EBUSY;
  107. }
  108. return 0;
  109. }
  110. /*
  111. * Communicate VQs size to PF to program CPT(0)_PF_Q(0-15)_CTL of the VF.
  112. * Must be ACKed.
  113. */
  114. int cptvf_send_vq_size_msg(struct cpt_vf *cptvf)
  115. {
  116. struct pci_dev *pdev = cptvf->pdev;
  117. struct cpt_mbox mbx = {};
  118. mbx.msg = CPT_MSG_QLEN;
  119. mbx.data = cptvf->qsize;
  120. if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
  121. dev_err(&pdev->dev, "PF didn't respond to vq_size msg\n");
  122. return -EBUSY;
  123. }
  124. return 0;
  125. }
  126. /*
  127. * Communicate VF group required to PF and get the VQ binded to that group
  128. */
  129. int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf)
  130. {
  131. struct pci_dev *pdev = cptvf->pdev;
  132. struct cpt_mbox mbx = {};
  133. mbx.msg = CPT_MSG_QBIND_GRP;
  134. /* Convey group of the VF */
  135. mbx.data = cptvf->vfgrp;
  136. if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
  137. dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
  138. return -EBUSY;
  139. }
  140. return 0;
  141. }
  142. /*
  143. * Communicate VF group required to PF and get the VQ binded to that group
  144. */
  145. int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf)
  146. {
  147. struct pci_dev *pdev = cptvf->pdev;
  148. struct cpt_mbox mbx = {};
  149. mbx.msg = CPT_MSG_VQ_PRIORITY;
  150. /* Convey group of the VF */
  151. mbx.data = cptvf->priority;
  152. if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
  153. dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
  154. return -EBUSY;
  155. }
  156. return 0;
  157. }
  158. /*
  159. * Communicate to PF that VF is UP and running
  160. */
  161. int cptvf_send_vf_up(struct cpt_vf *cptvf)
  162. {
  163. struct pci_dev *pdev = cptvf->pdev;
  164. struct cpt_mbox mbx = {};
  165. mbx.msg = CPT_MSG_VF_UP;
  166. if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
  167. dev_err(&pdev->dev, "PF didn't respond to UP msg\n");
  168. return -EBUSY;
  169. }
  170. return 0;
  171. }
  172. /*
  173. * Communicate to PF that VF is DOWN and running
  174. */
  175. int cptvf_send_vf_down(struct cpt_vf *cptvf)
  176. {
  177. struct pci_dev *pdev = cptvf->pdev;
  178. struct cpt_mbox mbx = {};
  179. mbx.msg = CPT_MSG_VF_DOWN;
  180. if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
  181. dev_err(&pdev->dev, "PF didn't respond to DOWN msg\n");
  182. return -EBUSY;
  183. }
  184. return 0;
  185. }