cptvf_mbox.c 4.3 KB

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